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 00364 void 00365 Sequence::add_var_nocopy(BaseType *bt, Part) 00366 { 00367 if (!bt) 00368 throw InternalErr(__FILE__, __LINE__, 00369 "Cannot add variable: NULL pointer"); 00370 bt->set_parent(this); 00371 _vars.push_back(bt); 00372 } 00373 00374 // Deprecated 00375 BaseType * 00376 Sequence::var(const string &n, btp_stack &s) 00377 { 00378 string name = www2id(n); 00379 00380 BaseType *btp = m_exact_match(name, &s); 00381 if (btp) 00382 return btp; 00383 00384 return m_leaf_match(name, &s); 00385 } 00386 00387 BaseType * 00388 Sequence::var(const string &name, bool exact_match, btp_stack *s) 00389 { 00390 string n = www2id(name); 00391 00392 if (exact_match) 00393 return m_exact_match(n, s); 00394 else 00395 return m_leaf_match(n, s); 00396 } 00397 00398 BaseType * 00399 Sequence::m_leaf_match(const string &name, btp_stack *s) 00400 { 00401 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00402 if ((*i)->name() == name) { 00403 if (s) 00404 s->push(static_cast<BaseType *>(this)); 00405 return *i; 00406 } 00407 if ((*i)->is_constructor_type()) { 00408 BaseType *btp = (*i)->var(name, false, s); 00409 if (btp) { 00410 if (s) 00411 s->push(static_cast<BaseType *>(this)); 00412 return btp; 00413 } 00414 } 00415 } 00416 00417 return 0; 00418 } 00419 00420 BaseType * 00421 Sequence::m_exact_match(const string &name, btp_stack *s) 00422 { 00423 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00424 if ((*i)->name() == name) { 00425 if (s) 00426 s->push(static_cast<BaseType *>(this)); 00427 return *i; 00428 } 00429 } 00430 00431 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00432 if (dot_pos != string::npos) { 00433 string aggregate = name.substr(0, dot_pos); 00434 string field = name.substr(dot_pos + 1); 00435 00436 BaseType *agg_ptr = var(aggregate); 00437 if (agg_ptr) { 00438 if (s) 00439 s->push(static_cast<BaseType *>(this)); 00440 return agg_ptr->var(field, true, s); // recurse 00441 } 00442 else 00443 return 0; // qualified names must be *fully* qualified 00444 } 00445 00446 return 0; 00447 } 00448 00453 BaseTypeRow * 00454 Sequence::row_value(size_t row) 00455 { 00456 if (row >= d_values.size()) 00457 return 0; 00458 return d_values[row]; 00459 } 00460 00467 void 00468 Sequence::set_value(SequenceValues &values) 00469 { 00470 d_values = values; 00471 } 00472 00475 SequenceValues 00476 Sequence::value() 00477 { 00478 return d_values; 00479 } 00480 00486 BaseType * 00487 Sequence::var_value(size_t row, const string &name) 00488 { 00489 BaseTypeRow *bt_row_ptr = row_value(row); 00490 if (!bt_row_ptr) 00491 return 0; 00492 00493 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin(); 00494 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end(); 00495 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name) 00496 ++bt_row_iter; 00497 00498 if (bt_row_iter == bt_row_end) 00499 return 0; 00500 else 00501 return *bt_row_iter; 00502 } 00503 00509 BaseType * 00510 Sequence::var_value(size_t row, size_t i) 00511 { 00512 BaseTypeRow *bt_row_ptr = row_value(row); 00513 if (!bt_row_ptr) 00514 return 0; 00515 00516 if (i >= bt_row_ptr->size()) 00517 return 0; 00518 00519 return (*bt_row_ptr)[i]; 00520 } 00521 00522 unsigned int 00523 Sequence::width() 00524 { 00525 unsigned int sz = 0; 00526 00527 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00528 sz += (*i)->width(); 00529 } 00530 00531 return sz; 00532 } 00533 00541 unsigned int 00542 Sequence::width(bool constrained) 00543 { 00544 unsigned int sz = 0; 00545 00546 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00547 if (constrained) { 00548 if ((*i)->send_p()) 00549 sz += (*i)->width(constrained); 00550 } 00551 else { 00552 sz += (*i)->width(constrained); 00553 } 00554 } 00555 00556 return sz; 00557 } 00558 00559 // This version returns -1. Each API-specific subclass should define a more 00560 // reasonable version. jhrg 5/24/96 00561 00577 int 00578 Sequence::length() 00579 { 00580 return -1; 00581 } 00582 00583 00584 int 00585 Sequence::number_of_rows() 00586 { 00587 return d_values.size(); 00588 } 00589 00593 void 00594 Sequence::reset_row_number() 00595 { 00596 d_row_number = -1; 00597 } 00598 00599 // Notes: 00600 // Assume that read() is implemented so that, when reading data for a nested 00601 // sequence, only the outer most level is *actually* read. 00602 // This is a consequence of our current (12/7/99) implementation of 00603 // the JGOFS server (which is the only server to actually use nested 00604 // sequences). 12/7/99 jhrg 00605 // 00606 // Stop assuming this. This logic is being moved into the JGOFS server 00607 // itself. 6/1/2001 jhrg 00608 00609 // The read() function returns a boolean value, with TRUE 00610 // indicating that read() should be called again because there's 00611 // more data to read, and FALSE indicating there's no more data 00612 // to read. Note that this behavior is necessary to properly 00613 // handle variables that contain Sequences. Jose Garcia If an 00614 // error exists while reading, the implementers of the surrogate 00615 // library SHOULD throw an Error object which will propagate 00616 // beyond this point to to the original caller. 00617 // Jose Garcia 00618 00651 bool 00652 Sequence::read_row(int row, DDS &dds, 00653 ConstraintEvaluator &eval, bool ce_eval) 00654 { 00655 DBG2(cerr << "Entering Sequence::read_row for " << name() << endl); 00656 if (row < d_row_number) 00657 throw InternalErr("Trying to back up inside a sequence!"); 00658 00659 DBG2(cerr << "read_row: row number " << row 00660 << ", current row " << d_row_number << endl); 00661 if (row == d_row_number) 00662 { 00663 DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl); 00664 return true; 00665 } 00666 00667 dds.timeout_on(); 00668 00669 int eof = 0; // Start out assuming EOF is false. 00670 while (!eof && d_row_number < row) { 00671 if (!read_p()) { 00672 eof = (read() == false); 00673 } 00674 00675 // Advance the row number if ce_eval is false (we're not supposed to 00676 // evaluate the selection) or both ce_eval and the selection are 00677 // true. 00678 if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) 00679 d_row_number++; 00680 00681 set_read_p(false); // ...so that the next instance will be read 00682 } 00683 00684 // Once we finish the above loop, set read_p to true so that the caller 00685 // knows that data *has* been read. This is how the read() methods of the 00686 // elements of the sequence know to not call read() but instead look for 00687 // data values inside themselves. 00688 set_read_p(true); 00689 00690 dds.timeout_off(); 00691 00692 // Return true if we have valid data, false if we've read to the EOF. 00693 DBG2(cerr << "Leaving Sequence::read_row for " << name() 00694 << " with " << (eof == 0) << endl); 00695 return eof == 0; 00696 } 00697 00698 // Private. This is used to process constraints on the rows of a sequence. 00699 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This 00700 // odd-looking logic first checks if d_ending_row_number is the sentinel 00701 // value of -1. If so, the sequence was not constrained by row number and 00702 // this method should never return true (which indicates that we're at the 00703 // end of a row-number constraint). If d_ending_row_number is not -1, then is 00704 // \e i at the end point? 6/1/2001 jhrg 00705 inline bool 00706 Sequence::is_end_of_rows(int i) 00707 { 00708 return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number)); 00709 } 00710 00771 bool 00772 Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, 00773 Marshaller &m, bool ce_eval) 00774 { 00775 DBG2(cerr << "Entering Sequence::serialize for " << name() << endl); 00776 00777 // Special case leaf sequences! 00778 if (is_leaf_sequence()) 00779 return serialize_leaf(dds, eval, m, ce_eval); 00780 else 00781 return serialize_parent_part_one(dds, eval, m); 00782 } 00783 00784 // We know this is not a leaf Sequence. That means that this Sequence holds 00785 // another Sequence as one of its fields _and_ that child Sequence triggers 00786 // the actual transmission of values. 00787 00788 bool 00789 Sequence::serialize_parent_part_one(DDS &dds, 00790 ConstraintEvaluator &eval, Marshaller &m) 00791 { 00792 DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl); 00793 00794 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00795 00796 // read_row returns true if valid data was read, false if the EOF was 00797 // found. 6/1/2001 jhrg 00798 // Since this is a parent sequence, read the row ignoring the CE (all of 00799 // the CE clauses will be evaluated by the leaf sequence). 00800 bool status = read_row(i, dds, eval, false); 00801 DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00802 00803 while (status && !is_end_of_rows(i)) { 00804 i += d_row_stride; 00805 00806 // DBG(cerr << "Writing Start of Instance marker" << endl); 00807 // write_start_of_instance(sink); 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 // Only call serialize for child Sequences; the leaf sequence 00812 // will trigger the transmission of values for its parents (this 00813 // sequence and maybe others) once it gets soem valid data to 00814 // send. 00815 // Note that if the leaf sequence has no variables in the current 00816 // projection, its serialize() method will never be called and that's 00817 // the method that triggers actually sending values. Thus the leaf 00818 // sequence must be the lowest level sequence with values whose send_p 00819 // property is true. 00820 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) 00821 (*iter)->serialize(eval, dds, m); 00822 } 00823 00824 set_read_p(false); // ...so this will read the next instance 00825 00826 status = read_row(i, dds, eval, false); 00827 DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00828 } 00829 // Reset current row number for next nested sequence element. 00830 d_row_number = -1; 00831 00832 // Always write the EOS marker? 12/23/04 jhrg 00833 // Yes. According to DAP2, a completely empty response is signalled by 00834 // a return value of only the EOS marker for the outermost sequence. 00835 if (d_top_most || d_wrote_soi) { 00836 DBG(cerr << "Writing End of Sequence marker" << endl); 00837 write_end_of_sequence(m); 00838 d_wrote_soi = false; 00839 } 00840 00841 return true; // Signal errors with exceptions. 00842 } 00843 00844 // If we are here then we know that this is 'parent sequence' and that the 00845 // leaf seq has found valid data to send. We also know that 00846 // serialize_parent_part_one has been called so data are in the instance's 00847 // fields. This is wheree we send data. Whereas ..._part_one() contains a 00848 // loop to iterate over all of rows in a parent sequence, this does not. This 00849 // method assumes that the serialize_leaf() will call it each time it needs 00850 // to be called. 00851 // 00852 // NB: This code only works if the child sequences appear after all other 00853 // variables. 00854 void 00855 Sequence::serialize_parent_part_two(DDS &dds, 00856 ConstraintEvaluator &eval, Marshaller &m) 00857 { 00858 DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl); 00859 00860 BaseType *btp = get_parent(); 00861 if (btp && btp->type() == dods_sequence_c) 00862 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m); 00863 00864 if (d_unsent_data) { 00865 DBG(cerr << "Writing Start of Instance marker" << endl); 00866 d_wrote_soi = true; 00867 write_start_of_instance(m); 00868 00869 // In this loop serialize will signal an error with an exception. 00870 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00871 // Send all the non-sequence variables 00872 DBG(cerr << "Sequence::serialize_parent_part_two(), serializing " 00873 << (*iter)->name() << endl); 00874 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 00875 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00876 (*iter)->serialize(eval, dds, m, false); 00877 } 00878 } 00879 00880 d_unsent_data = false; // read should set this. 00881 } 00882 } 00883 00884 // This code is only run by a leaf sequence. Note that a one level sequence 00885 // is also a leaf sequence. 00886 bool 00887 Sequence::serialize_leaf(DDS &dds, 00888 ConstraintEvaluator &eval, Marshaller &m, bool ce_eval) 00889 { 00890 DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl); 00891 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00892 00893 // read_row returns true if valid data was read, false if the EOF was 00894 // found. 6/1/2001 jhrg 00895 bool status = read_row(i, dds, eval, ce_eval); 00896 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00897 00898 // Once the first valid (satisfies the CE) row of the leaf sequence has 00899 // been read, we know we're going to send data. Send the current instance 00900 // of the parent/ancestor sequences now, if there are any. We only need 00901 // to do this once, hence it's not inside the while loop, but we only 00902 // send the parent seq data _if_ there's data in the leaf to send, that's 00903 // why we wait until after the first call to read_row() here in the leaf 00904 // sequence. 00905 // 00906 // NB: It's important to only call serialize_parent_part_two() for a 00907 // Sequence that really is the parent of a leaf sequence. The fancy cast 00908 // will throw and exception if btp is not a Sequence, but doesn't test 00909 // that it's a parent sequence as we've defined them here. 00910 if (status && !is_end_of_rows(i)) { 00911 BaseType *btp = get_parent(); 00912 if (btp && btp->type() == dods_sequence_c) 00913 dynamic_cast<Sequence&>(*btp).serialize_parent_part_two(dds, 00914 eval, m); 00915 } 00916 00917 d_wrote_soi = false; 00918 while (status && !is_end_of_rows(i)) { 00919 i += d_row_stride; 00920 00921 DBG(cerr << "Writing Start of Instance marker" << endl); 00922 d_wrote_soi = true; 00923 write_start_of_instance(m); 00924 00925 // In this loop serialize will signal an error with an exception. 00926 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 00927 DBG(cerr << "Sequence::serialize_leaf(), serializing " 00928 << (*iter)->name() << endl); 00929 if ((*iter)->send_p()) { 00930 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00931 (*iter)->serialize(eval, dds, m, false); 00932 } 00933 } 00934 00935 set_read_p(false); // ...so this will read the next instance 00936 00937 status = read_row(i, dds, eval, ce_eval); 00938 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00939 } 00940 00941 // Only write the EOS marker if there's a matching Start Of Instnace 00942 // Marker in the stream. 00943 if (d_wrote_soi || d_top_most) { 00944 DBG(cerr << "Writing End of Sequence marker" << endl); 00945 write_end_of_sequence(m); 00946 } 00947 00948 return true; // Signal errors with exceptions. 00949 } 00950 00973 void 00974 Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds) 00975 { 00976 DBG(cerr << "Sequence::intern_data - for " << name() << endl); 00977 DBG2(cerr << " intern_data, values: " << &d_values << endl); 00978 00979 // Why use a stack instead of return values? We need the stack because 00980 // Sequences neted three of more levels deep will loose the middle 00981 // instances when the intern_data_parent_part_two() code is run. 00982 sequence_values_stack_t sequence_values_stack; 00983 00984 DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values 00985 << ") on stack; size: " << sequence_values_stack.size() << endl); 00986 sequence_values_stack.push(&d_values); 00987 00988 intern_data_private(eval, dds, sequence_values_stack); 00989 } 00990 00991 void 00992 Sequence::intern_data_private(ConstraintEvaluator &eval, 00993 DDS &dds, 00994 sequence_values_stack_t &sequence_values_stack) 00995 { 00996 DBG(cerr << "Entering intern_data_private for " << name() << endl); 00997 00998 if (is_leaf_sequence()) 00999 intern_data_for_leaf(dds, eval, sequence_values_stack); 01000 else 01001 intern_data_parent_part_one(dds, eval, sequence_values_stack); 01002 } 01003 01004 void 01005 Sequence::intern_data_parent_part_one(DDS & dds, 01006 ConstraintEvaluator & eval, 01007 sequence_values_stack_t & 01008 sequence_values_stack) 01009 { 01010 DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl); 01011 01012 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 01013 01014 // read_row returns true if valid data was read, false if the EOF was 01015 // found. 6/1/2001 jhrg 01016 // Since this is a parent sequence, read the row ignoring the CE (all of 01017 // the CE clauses will be evaluated by the leaf sequence). 01018 bool status = read_row(i, dds, eval, false); 01019 01020 // Grab the current size of the value stack. We do this because it is 01021 // possible that no nested sequences for this row happened to be 01022 // selected because of a constract evaluation or the last row is not 01023 // selected because of a constraint evaluation. In either case, no 01024 // nested sequence d_values are pused onto the stack, so there is 01025 // nothing to pop at the end of this function. pcw 07/14/08 01026 SequenceValues::size_type orig_stack_size = sequence_values_stack.size() ; 01027 01028 while (status 01029 && (get_ending_row_number() == -1 01030 || i <= get_ending_row_number())) 01031 { 01032 i += get_row_stride(); 01033 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01034 if ((*iter)->send_p()) { 01035 switch ((*iter)->type()) { 01036 case dods_sequence_c: 01037 dynamic_cast<Sequence&>(**iter).intern_data_private( 01038 eval, dds, sequence_values_stack); 01039 break; 01040 01041 default: 01042 (*iter)->intern_data(eval, dds); 01043 break; 01044 } 01045 } 01046 } 01047 01048 set_read_p(false); // ...so this will read the next instance 01049 01050 status = read_row(i, dds, eval, false); 01051 } 01052 01053 // Reset current row number for next nested sequence element. 01054 reset_row_number(); 01055 01056 // if the size of the stack is larger than the original size (retrieved 01057 // above) then pop the top set of d_values from the stack. If it's the 01058 // same, then no nested sequences, or possible the last nested sequence, 01059 // were pushed onto the stack, so there is nothing to pop. 01060 if( sequence_values_stack.size() > orig_stack_size ) 01061 { 01062 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01063 << ") off stack; size: " << sequence_values_stack.size() << endl); 01064 sequence_values_stack.pop(); 01065 } 01066 DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl); 01067 } 01068 01069 void 01070 Sequence::intern_data_parent_part_two(DDS &dds, 01071 ConstraintEvaluator &eval, 01072 sequence_values_stack_t &sequence_values_stack) 01073 { 01074 DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl); 01075 01076 BaseType *btp = get_parent(); 01077 if (btp && btp->type() == dods_sequence_c) { 01078 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01079 dds, eval, sequence_values_stack); 01080 } 01081 01082 DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl); 01083 SequenceValues *values = sequence_values_stack.top(); 01084 DBG2(cerr << " using values = " << (void *)values << endl); 01085 01086 if (get_unsent_data()) { 01087 BaseTypeRow *row_data = new BaseTypeRow; 01088 01089 // In this loop transfer_data will signal an error with an exception. 01090 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01091 01092 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 01093 row_data->push_back((*iter)->ptr_duplicate()); 01094 } 01095 else if ((*iter)->send_p()) { //Sequence; must be the last variable 01096 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate()); 01097 if (!tmp) { 01098 delete row_data; 01099 throw InternalErr(__FILE__, __LINE__, "Expected a Sequence."); 01100 } 01101 row_data->push_back(tmp); 01102 DBG2(cerr << " pushing d_values of " << tmp->name() 01103 << " (" << &(tmp->d_values) 01104 << ") on stack; size: " << sequence_values_stack.size() 01105 << endl); 01106 // This pushes the d_values field of the newly created leaf 01107 // Sequence onto the stack. The code then returns to intern 01108 // _data_for_leaf() where this value will be used. 01109 sequence_values_stack.push(&(tmp->d_values)); 01110 } 01111 } 01112 01113 DBG2(cerr << " pushing values for " << name() 01114 << " to " << values << endl); 01115 values->push_back(row_data); 01116 set_unsent_data(false); 01117 } 01118 DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl); 01119 } 01120 01121 void 01122 Sequence::intern_data_for_leaf(DDS &dds, 01123 ConstraintEvaluator &eval, 01124 sequence_values_stack_t &sequence_values_stack) 01125 { 01126 DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl); 01127 01128 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 01129 01130 DBG2(cerr << " reading row " << i << endl); 01131 bool status = read_row(i, dds, eval, true); 01132 DBG2(cerr << " status: " << status << endl); 01133 DBG2(cerr << " ending row number: " << get_ending_row_number() << endl); 01134 01135 if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 01136 BaseType *btp = get_parent(); 01137 if (btp && btp->type() == dods_sequence_c) { 01138 // This call will read the values for the parent sequences and 01139 // then allocate a new instance for the leaf and push that onto 01140 // the stack. 01141 dynamic_cast<Sequence&>(*btp).intern_data_parent_part_two( 01142 dds, eval, sequence_values_stack); 01143 } 01144 01145 // intern_data_parent_part_two pushes the d_values field of the leaf 01146 // onto the stack, so this operation grabs that value and then loads 01147 // data into it. 01148 SequenceValues *values = sequence_values_stack.top(); 01149 DBG2(cerr << " using values = " << values << endl); 01150 01151 while (status && (get_ending_row_number() == -1 01152 || i <= get_ending_row_number())) { 01153 i += get_row_stride(); 01154 01155 // Copy data from the object's fields to this new BaeTypeRow instance 01156 BaseTypeRow *row_data = new BaseTypeRow; 01157 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01158 if ((*iter)->send_p()) { 01159 row_data->push_back((*iter)->ptr_duplicate()); 01160 } 01161 } 01162 01163 DBG2(cerr << " pushing values for " << name() 01164 << " to " << values << endl); 01165 // Save the row_data to values(). 01166 values->push_back(row_data); 01167 01168 set_read_p(false); // ...so this will read the next instance 01169 // Read the ith row into this object's fields 01170 status = read_row(i, dds, eval, true); 01171 } 01172 01173 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01174 << ") off stack; size: " << sequence_values_stack.size() << endl); 01175 sequence_values_stack.pop(); 01176 } 01177 DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl); 01178 } 01179 01200 bool 01201 Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 01202 { 01203 DataDDS *dd = dynamic_cast<DataDDS *>(dds); 01204 if (!dd) 01205 throw InternalErr("Expected argument 'dds' to be a DataDDS!"); 01206 01207 DBG2(cerr << "Reading from server/protocol version: " 01208 << dd->get_protocol_major() << "." << dd->get_protocol_minor() 01209 << endl); 01210 01211 // Check for old servers. 01212 if (dd->get_protocol_major() < 2) { 01213 throw Error(string("The protocl version (") + dd->get_protocol() 01214 + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator."); 01215 } 01216 01217 while (true) { 01218 // Grab the sequence stream's marker. 01219 unsigned char marker = read_marker(um); 01220 if (is_end_of_sequence(marker)) 01221 break; // EXIT the while loop here!!! 01222 else if (is_start_of_instance(marker)) { 01223 d_row_number++; 01224 DBG2(cerr << "Reading row " << d_row_number << " of " 01225 << name() << endl); 01226 BaseTypeRow *bt_row_ptr = new BaseTypeRow; 01227 // Read the instance's values, building up the row 01228 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01229 BaseType *bt_ptr = (*iter)->ptr_duplicate(); 01230 bt_ptr->deserialize(um, dds, reuse); 01231 DBG2(cerr << "Deserialized " << bt_ptr->name() << " (" 01232 << bt_ptr << ") = "); 01233 DBG2(bt_ptr->print_val(stderr, "")); 01234 bt_row_ptr->push_back(bt_ptr); 01235 } 01236 // Append this row to those accumulated. 01237 d_values.push_back(bt_row_ptr); 01238 } 01239 else 01240 throw Error("I could not read the expected Sequence data stream marker!"); 01241 }; 01242 01243 return false; 01244 } 01245 01246 // Return the current row number. 01247 01259 int 01260 Sequence::get_starting_row_number() 01261 { 01262 return d_starting_row_number; 01263 } 01264 01275 int 01276 Sequence::get_row_stride() 01277 { 01278 return d_row_stride; 01279 } 01280 01292 int 01293 Sequence::get_ending_row_number() 01294 { 01295 return d_ending_row_number; 01296 } 01297 01306 void 01307 Sequence::set_row_number_constraint(int start, int stop, int stride) 01308 { 01309 if (stop < start) 01310 throw Error(malformed_expr, "Starting row number must precede the ending row number."); 01311 01312 d_starting_row_number = start; 01313 d_row_stride = stride; 01314 d_ending_row_number = stop; 01315 } 01316 01319 unsigned int 01320 Sequence::val2buf(void *, bool) 01321 { 01322 throw InternalErr(__FILE__, __LINE__, "Never use this method; see the programmer's guide documentation."); 01323 return sizeof(Sequence); 01324 } 01325 01330 unsigned int 01331 Sequence::buf2val(void **) 01332 { 01333 throw InternalErr(__FILE__, __LINE__, "Use Sequence::var_value() or Sequence::row_value() in place of Sequence::buf2val()"); 01334 return sizeof(Sequence); 01335 } 01336 01337 #if FILE_METHODS 01338 void 01339 Sequence::print_one_row(FILE *out, int row, string space, 01340 bool print_row_num) 01341 { 01342 if (print_row_num) 01343 fprintf(out, "\n%s%d: ", space.c_str(), row) ; 01344 01345 fprintf(out, "{ ") ; 01346 01347 int elements = element_count() - 1; 01348 int j; 01349 BaseType *bt_ptr; 01350 // Print first N-1 elements of the row. 01351 for (j = 0; j < elements; ++j) { 01352 bt_ptr = var_value(row, j); 01353 if (bt_ptr) { // data 01354 if (bt_ptr->type() == dods_sequence_c) 01355 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01356 (out, space + " ", false, print_row_num); 01357 else 01358 bt_ptr->print_val(out, space, false); 01359 fprintf(out, ", ") ; 01360 } 01361 } 01362 01363 // Print Nth element; end with a `}.' 01364 bt_ptr = var_value(row, j); 01365 if (bt_ptr) { // data 01366 if (bt_ptr->type() == dods_sequence_c) 01367 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01368 (out, space + " ", false, print_row_num); 01369 else 01370 bt_ptr->print_val(out, space, false); 01371 } 01372 01373 fprintf(out, " }") ; 01374 } 01375 #endif 01376 01377 void 01378 Sequence::print_one_row(ostream &out, int row, string space, 01379 bool print_row_num) 01380 { 01381 if (print_row_num) 01382 out << "\n" << space << row << ": " ; 01383 01384 out << "{ " ; 01385 01386 int elements = element_count(); 01387 int j = 0; 01388 BaseType *bt_ptr = 0; 01389 01390 // This version of print_one_row() works for both data read with 01391 // deserialize(), where each variable is assumed to have valid data, and 01392 // intern_data(), where some/many variables do not. Because of that, it's 01393 // not correct to assume that all of the elements will be printed, which 01394 // is what the old code did. 01395 // Print the first value 01396 while (j < elements && !bt_ptr) { 01397 bt_ptr = var_value(row, j++); 01398 if (bt_ptr) { // data 01399 if (bt_ptr->type() == dods_sequence_c) 01400 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01401 (out, space + " ", false, print_row_num); 01402 else 01403 bt_ptr->print_val(out, space, false); 01404 } 01405 } 01406 01407 // Print the remaining values 01408 while (j < elements) { 01409 bt_ptr = var_value(row, j++); 01410 if (bt_ptr) { // data 01411 out << ", "; 01412 if (bt_ptr->type() == dods_sequence_c) 01413 dynamic_cast<Sequence*>(bt_ptr)->print_val_by_rows 01414 (out, space + " ", false, print_row_num); 01415 else 01416 bt_ptr->print_val(out, space, false); 01417 } 01418 } 01419 01420 out << " }" ; 01421 } 01422 01423 #if FILE_METHODS 01424 void 01425 Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, 01426 bool print_row_numbers) 01427 { 01428 if (print_decl_p) { 01429 print_decl(out, space, false); 01430 fprintf(out, " = ") ; 01431 } 01432 01433 fprintf(out, "{ ") ; 01434 01435 int rows = number_of_rows() - 1; 01436 int i; 01437 for (i = 0; i < rows; ++i) { 01438 print_one_row(out, i, space, print_row_numbers); 01439 fprintf(out, ", ") ; 01440 } 01441 print_one_row(out, i, space, print_row_numbers); 01442 01443 fprintf(out, " }") ; 01444 01445 if (print_decl_p) 01446 fprintf(out, ";\n") ; 01447 } 01448 #endif 01449 01450 void 01451 Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, 01452 bool print_row_numbers) 01453 { 01454 if (print_decl_p) { 01455 print_decl(out, space, false); 01456 out << " = " ; 01457 } 01458 01459 out << "{ " ; 01460 01461 int rows = number_of_rows() - 1; 01462 int i; 01463 for (i = 0; i < rows; ++i) { 01464 print_one_row(out, i, space, print_row_numbers); 01465 out << ", " ; 01466 } 01467 print_one_row(out, i, space, print_row_numbers); 01468 01469 out << " }" ; 01470 01471 if (print_decl_p) 01472 out << ";\n" ; 01473 } 01474 01475 #if FILE_METHODS 01476 void 01477 Sequence::print_val(FILE *out, string space, bool print_decl_p) 01478 { 01479 print_val_by_rows(out, space, print_decl_p, false); 01480 } 01481 #endif 01482 01483 void 01484 Sequence::print_val(ostream &out, string space, bool print_decl_p) 01485 { 01486 print_val_by_rows(out, space, print_decl_p, false); 01487 } 01488 01489 01490 bool 01491 Sequence::check_semantics(string &msg, bool all) 01492 { 01493 if (!BaseType::check_semantics(msg)) 01494 return false; 01495 01496 if (!unique_names(_vars, name(), type_name(), msg)) 01497 return false; 01498 01499 if (all) 01500 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 01501 if (!(*i)->check_semantics(msg, true)) { 01502 return false; 01503 } 01504 } 01505 01506 return true; 01507 } 01508 01509 void 01510 Sequence::set_leaf_p(bool state) 01511 { 01512 d_leaf_sequence = state; 01513 } 01514 01515 bool 01516 Sequence::is_leaf_sequence() 01517 { 01518 return d_leaf_sequence; 01519 } 01520 01545 void 01546 Sequence::set_leaf_sequence(int lvl) 01547 { 01548 bool has_child_sequence = false; 01549 01550 if (lvl == 1) d_top_most = true; 01551 01552 DBG2(cerr << "Processing sequence " << name() << endl); 01553 01554 for (Vars_iter iter = _vars.begin(); iter != _vars.end(); iter++) { 01555 // About the test for send_p(): Only descend into a sequence if it has 01556 // fields that might be sent. Thus if, in a two-level sequence, nothing 01557 // in the lower level is to be sent, the upper level is marked as the 01558 // leaf sequence. This ensures that values _will_ be sent (see the comment 01559 // in serialize_leaf() and serialize_parent_part_one()). 01560 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) { 01561 if (has_child_sequence) 01562 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator."); 01563 01564 has_child_sequence = true; 01565 dynamic_cast<Sequence&>(**iter).set_leaf_sequence(++lvl); 01566 } 01567 else if ((*iter)->type() == dods_structure_c) { 01568 dynamic_cast<Structure&>(**iter).set_leaf_sequence(lvl); 01569 } 01570 } 01571 01572 if (!has_child_sequence) 01573 set_leaf_p(true); 01574 else 01575 set_leaf_p(false); 01576 01577 DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl); 01578 } 01579 01588 void 01589 Sequence::dump(ostream &strm) const 01590 { 01591 strm << DapIndent::LMarg << "Sequence::dump - (" 01592 << (void *)this << ")" << endl ; 01593 DapIndent::Indent() ; 01594 Constructor::dump(strm) ; 01595 strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number 01596 << endl ; 01597 strm << DapIndent::LMarg << "bracket notation information:" << endl ; 01598 DapIndent::Indent() ; 01599 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number 01600 << endl ; 01601 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl ; 01602 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number 01603 << endl ; 01604 DapIndent::UnIndent() ; 01605 01606 strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl ; 01607 strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl ; 01608 strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence 01609 << endl ; 01610 strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most 01611 << endl ; 01612 DapIndent::UnIndent() ; 01613 } 01614 01615 } // namespace libdap 01616