libdap
Updated for version 3.17.0
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 //#define DODS_DEBUG 00036 //#define DODS_DEBUG2 00037 00038 #include "config.h" 00039 00040 #include <algorithm> 00041 #include <string> 00042 #include <sstream> 00043 00044 #include "Byte.h" 00045 #include "Int16.h" 00046 #include "UInt16.h" 00047 #include "Int32.h" 00048 #include "UInt32.h" 00049 #include "Float32.h" 00050 #include "Float64.h" 00051 #include "Str.h" 00052 #include "Url.h" 00053 #include "Array.h" 00054 #include "Structure.h" 00055 #include "Sequence.h" 00056 #include "Grid.h" 00057 00058 #include "Marshaller.h" 00059 #include "UnMarshaller.h" 00060 00061 #include "debug.h" 00062 #include "Error.h" 00063 #include "InternalErr.h" 00064 #include "Sequence.h" 00065 #include "DDS.h" 00066 #include "DataDDS.h" 00067 #include "util.h" 00068 #include "InternalErr.h" 00069 #include "escaping.h" 00070 00071 #include "D4Attributes.h" 00072 #include "D4Sequence.h" 00073 #include "D4Group.h" 00074 #include "Constructor.h" 00075 #include "DMR.h" 00076 00077 #undef CLEAR_LOCAL_DATA 00078 00079 using namespace std; 00080 00081 namespace libdap { 00082 00083 static const unsigned char end_of_sequence = 0xA5; // binary pattern 1010 0101 00084 static const unsigned char start_of_instance = 0x5A; // binary pattern 0101 1010 00085 00086 // Private member functions 00087 00088 void Sequence::m_duplicate(const Sequence &s) 00089 { 00090 DBG(cerr << "In Sequence::m_duplicate" << endl); 00091 00092 d_row_number = s.d_row_number; 00093 d_starting_row_number = s.d_starting_row_number; 00094 d_ending_row_number = s.d_ending_row_number; 00095 d_row_stride = s.d_row_stride; 00096 d_leaf_sequence = s.d_leaf_sequence; 00097 d_unsent_data = s.d_unsent_data; 00098 d_wrote_soi = s.d_wrote_soi; 00099 d_top_most = s.d_top_most; 00100 00101 Sequence &cs = const_cast<Sequence &>(s); 00102 00103 // Copy the BaseType objects used to hold values. 00104 for (vector<BaseTypeRow *>::iterator rows_iter = cs.d_values.begin(); rows_iter != cs.d_values.end(); rows_iter++) { 00105 // Get the current BaseType Row 00106 BaseTypeRow *src_bt_row_ptr = *rows_iter; 00107 // Create a new row. 00108 BaseTypeRow *dest_bt_row_ptr = new BaseTypeRow; 00109 // Copy the BaseType objects from a row to new BaseType objects. 00110 // Push new BaseType objects onto new row. 00111 for (BaseTypeRow::iterator bt_row_iter = src_bt_row_ptr->begin(); bt_row_iter != src_bt_row_ptr->end(); 00112 bt_row_iter++) { 00113 BaseType *src_bt_ptr = *bt_row_iter; 00114 BaseType *dest_bt_ptr = src_bt_ptr->ptr_duplicate(); 00115 dest_bt_row_ptr->push_back(dest_bt_ptr); 00116 } 00117 // Push new row onto d_values. 00118 d_values.push_back(dest_bt_row_ptr); 00119 } 00120 } 00121 00122 static void write_end_of_sequence(Marshaller &m) 00123 { 00124 m.put_opaque((char *) &end_of_sequence, 1); 00125 } 00126 00127 static void write_start_of_instance(Marshaller &m) 00128 { 00129 m.put_opaque((char *) &start_of_instance, 1); 00130 } 00131 00132 static unsigned char 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 is_start_of_instance(unsigned char marker) 00141 { 00142 return (marker == start_of_instance); 00143 } 00144 00145 static bool is_end_of_sequence(unsigned char marker) 00146 { 00147 return (marker == end_of_sequence); 00148 } 00149 00150 // Public member functions 00151 00160 Sequence::Sequence(const string &n) : 00161 Constructor(n, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), d_row_stride(1), d_ending_row_number( 00162 -1), d_unsent_data(false), d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false) 00163 { 00164 } 00165 00176 Sequence::Sequence(const string &n, const string &d) : 00177 Constructor(n, d, dods_sequence_c), d_row_number(-1), d_starting_row_number(-1), 00178 d_row_stride(1), d_ending_row_number(-1), d_unsent_data(false), 00179 d_wrote_soi(false), d_leaf_sequence(false), d_top_most(false) 00180 { 00181 } 00182 00184 Sequence::Sequence(const Sequence &rhs) : 00185 Constructor(rhs) 00186 { 00187 m_duplicate(rhs); 00188 } 00189 00190 BaseType * 00191 Sequence::ptr_duplicate() 00192 { 00193 return new Sequence(*this); 00194 } 00195 00210 BaseType * 00211 Sequence::transform_to_dap4(D4Group *root, Constructor *container) 00212 { 00213 D4Sequence *dest = new D4Sequence(name()); 00214 00215 Constructor::transform_to_dap4(root, dest); 00216 00217 dest->set_length(-1); 00218 dest->set_parent(container); 00219 00220 return dest; 00221 } 00222 00223 static inline void delete_bt(BaseType *bt_ptr) 00224 { 00225 delete bt_ptr; 00226 bt_ptr = 0; 00227 } 00228 00229 static inline void delete_rows(BaseTypeRow *bt_row_ptr) 00230 { 00231 for_each(bt_row_ptr->begin(), bt_row_ptr->end(), delete_bt); 00232 00233 delete bt_row_ptr; 00234 bt_row_ptr = 0; 00235 } 00236 00237 Sequence::~Sequence() 00238 { 00239 clear_local_data(); 00240 } 00241 00242 void Sequence::clear_local_data() 00243 { 00244 if (!d_values.empty()) { 00245 for_each(d_values.begin(), d_values.end(), delete_rows); 00246 d_values.resize(0); 00247 } 00248 00249 set_read_p(false); 00250 } 00251 00252 Sequence & 00253 Sequence::operator=(const Sequence &rhs) 00254 { 00255 if (this == &rhs) return *this; 00256 00257 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00258 00259 m_duplicate(rhs); 00260 00261 return *this; 00262 } 00263 00267 bool Sequence::is_dap2_only_type() 00268 { 00269 return true; 00270 } 00271 00272 string Sequence::toString() 00273 { 00274 ostringstream oss; 00275 00276 oss << BaseType::toString(); 00277 00278 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00279 oss << (*i)->toString(); 00280 } 00281 00282 oss << endl; 00283 00284 return oss.str(); 00285 } 00286 00287 bool Sequence::is_linear() 00288 { 00289 bool linear = true; 00290 bool seq_found = false; 00291 for (Vars_iter iter = d_vars.begin(); linear && iter != d_vars.end(); iter++) { 00292 if ((*iter)->type() == dods_sequence_c) { 00293 // A linear sequence cannot have more than one child seq. at any 00294 // one level. If we've already found a seq at this level, return 00295 // false. 00296 if (seq_found) { 00297 linear = false; 00298 break; 00299 } 00300 seq_found = true; 00301 linear = static_cast<Sequence *>((*iter))->is_linear(); 00302 } 00303 else if ((*iter)->type() == dods_structure_c) { 00304 linear = static_cast<Structure*>((*iter))->is_linear(); 00305 } 00306 else { 00307 // A linear sequence cannot have Arrays, Lists or Grids. 00308 linear = (*iter)->is_simple_type(); 00309 } 00310 } 00311 00312 return linear; 00313 } 00314 00319 BaseTypeRow * 00320 Sequence::row_value(size_t row) 00321 { 00322 if (row >= d_values.size()) return 0; 00323 return d_values[row]; 00324 } 00325 00332 void Sequence::set_value(SequenceValues &values) 00333 { 00334 d_values = values; 00335 } 00336 00339 SequenceValues Sequence::value() 00340 { 00341 return d_values; 00342 } 00343 00346 SequenceValues & 00347 Sequence::value_ref() 00348 { 00349 return d_values; 00350 } 00351 00357 BaseType * 00358 Sequence::var_value(size_t row, const string &name) 00359 { 00360 BaseTypeRow *bt_row_ptr = row_value(row); 00361 if (!bt_row_ptr) return 0; 00362 00363 BaseTypeRow::iterator bt_row_iter = bt_row_ptr->begin(); 00364 BaseTypeRow::iterator bt_row_end = bt_row_ptr->end(); 00365 while (bt_row_iter != bt_row_end && (*bt_row_iter)->name() != name) 00366 ++bt_row_iter; 00367 00368 if (bt_row_iter == bt_row_end) 00369 return 0; 00370 else 00371 return *bt_row_iter; 00372 } 00373 00379 BaseType * 00380 Sequence::var_value(size_t row, size_t i) 00381 { 00382 BaseTypeRow *bt_row_ptr = row_value(row); 00383 if (!bt_row_ptr) return 0; 00384 00385 if (i >= bt_row_ptr->size()) return 0; 00386 00387 return (*bt_row_ptr)[i]; 00388 } 00389 00390 // This version returns -1. Each API-specific subclass should define a more 00391 // reasonable version. jhrg 5/24/96 00392 00408 int Sequence::length() const 00409 { 00410 return -1; 00411 } 00412 00413 // Hmmm. how is this different from length()? 00414 int Sequence::number_of_rows() const 00415 { 00416 return d_values.size(); 00417 } 00418 00422 void Sequence::reset_row_number() 00423 { 00424 d_row_number = -1; 00425 } 00426 00427 #if 0 00428 // written but not used - this was written so that values loaded from 00429 // Arrays into a new ('synthesized') sequence by the 'tablar() server 00430 // function would be properly used during the evaluation of a selection 00431 // expression. But I forgot that tabular() uses a specialized version of 00432 // Sequence: TabularSequence and that has it's own version of serialize(). 00433 // To get the returnAs="ascii" to filter values, I also need to specialize 00434 // the intern_data() method of Sequence. jhrg 3/9/15 00435 00450 void Sequence::load_prototypes_with_values(int row_number) 00451 { 00452 vector<BaseType*> *row = d_values.at(row_number); 00453 00454 // For each of the prototype variables in the Sequence, load it 00455 // with a values from the BaseType* vector. The order should match. 00456 // Test the type, but assume if that matches, the value is correct 00457 // for the variable. 00458 int pos = 0; 00459 for (Vars_iter i = var_begin(), e = var_end(); i != e; ++i) { 00460 if ((*i)->type() != row->at(pos)->var()->type()) 00461 throw InternalErr(__FILE__, __LINE__, "Expected types to match when loading values for selection expression evaluation."); 00462 00463 // Ugly... 00464 switch ((*i)->type()) { 00465 case dods_byte_c: 00466 static_cast<Byte*>(*i)->set_value(static_cast<Byte*>(row->at(pos++))->value()); 00467 break; 00468 case dods_int16_c: 00469 static_cast<Int16*>(*i)->set_value(static_cast<Int16*>(row->at(pos++))->value()); 00470 break; 00471 case dods_int32_c: 00472 static_cast<Int32*>(*i)->set_value(static_cast<Int32*>(row->at(pos++))->value()); 00473 break; 00474 case dods_uint16_c: 00475 static_cast<UInt16*>(*i)->set_value(static_cast<UInt16*>(row->at(pos++))->value()); 00476 break; 00477 case dods_uint32_c: 00478 static_cast<UInt32*>(*i)->set_value(static_cast<UInt32*>(row->at(pos++))->value()); 00479 break; 00480 case dods_float32_c: 00481 static_cast<Float32*>(*i)->set_value(static_cast<Float32*>(row->at(pos++))->value()); 00482 break; 00483 case dods_float64_c: 00484 static_cast<Float64*>(*i)->set_value(static_cast<Float64*>(row->at(pos++))->value()); 00485 break; 00486 case dods_str_c: 00487 static_cast<Str*>(*i)->set_value(static_cast<Str*>(row->at(pos++))->value()); 00488 break; 00489 case dods_url_c: 00490 static_cast<Url*>(*i)->set_value(static_cast<Url*>(row->at(pos++))->value()); 00491 break; 00492 default: 00493 throw InternalErr(__FILE__, __LINE__, "Expected a scalar type when loading values for selection expression evaluation."); 00494 } 00495 } 00496 } 00497 00498 #endif 00499 00500 // Notes: 00501 // Assume that read() is implemented so that, when reading data for a nested 00502 // sequence, only the outer most level is *actually* read. 00503 // This is a consequence of our current (12/7/99) implementation of 00504 // the JGOFS server (which is the only server to actually use nested 00505 // sequences). 12/7/99 jhrg 00506 // 00507 // Stop assuming this. This logic is being moved into the JGOFS server 00508 // itself. 6/1/2001 jhrg 00509 00510 // The read() function returns a boolean value, with TRUE 00511 // indicating that read() should be called again because there's 00512 // more data to read, and FALSE indicating there's no more data 00513 // to read. Note that this behavior is necessary to properly 00514 // handle variables that contain Sequences. Jose Garcia If an 00515 // error exists while reading, the implementers of the surrogate 00516 // library SHOULD throw an Error object which will propagate 00517 // beyond this point to to the original caller. 00518 // Jose Garcia 00519 00552 bool Sequence::read_row(int row, DDS &dds, ConstraintEvaluator &eval, bool ce_eval) 00553 { 00554 DBG2(cerr << "Entering Sequence::read_row for " << name() << endl); 00555 if (row < d_row_number) throw InternalErr("Trying to back up inside a sequence!"); 00556 00557 DBG2(cerr << "read_row: row number " << row << ", current row " << d_row_number << endl); 00558 if (row == d_row_number) { 00559 DBG2(cerr << "Leaving Sequence::read_row for " << name() << endl); 00560 return false; 00561 } 00562 #if USE_LOCAL_TIMEOUT_SCHEME 00563 dds.timeout_on(); 00564 #endif 00565 bool eof = false; // Start out assuming EOF is false. 00566 while (!eof && d_row_number < row) { 00567 if (!read_p()) { 00568 // jhrg original version from 10/9/13 : eof = (read() == false); 00569 eof = read(); 00570 } 00571 #if 0 00572 // A change (3/9/15): I've made the is_synthesized property 00573 // work so that the prototype variables in the Sequence are loaded 00574 // with the scalar values for the ith row so that the eval_selection() 00575 // method will function correctly. 00576 00577 // See note above 00578 00579 if (d_is_synthesized) { 00580 load_prototypes_with_values(d_row_number); 00581 } 00582 #endif 00583 // Advance the row number if ce_eval is false (we're not supposed to 00584 // evaluate the selection) or both ce_eval and the selection are 00585 // true. 00586 if (!eof && (!ce_eval || eval.eval_selection(dds, dataset()))) d_row_number++; 00587 00588 set_read_p(false); // ...so that the next instance will be read 00589 } 00590 00591 // Once we finish the above loop, set read_p to true so that the caller 00592 // knows that data *has* been read. This is how the read() methods of the 00593 // elements of the sequence know to not call read() but instead look for 00594 // data values inside themselves. 00595 set_read_p(true); 00596 #if USE_LOCAL_TIMEOUT_SCHEME 00597 dds.timeout_off(); 00598 #endif 00599 // Return true if we have valid data, false if we've read to the EOF. 00600 DBG2(cerr << "Leaving Sequence::read_row for " << name() << " with eof: " << eof << endl); 00601 return !eof; // jhrg 10/10/13 was: eof == 0; 00602 } 00603 00604 // Private. This is used to process constraints on the rows of a sequence. 00605 // Starting with 3.2 we support constraints like Sequence[10:2:20]. This 00606 // odd-looking logic first checks if d_ending_row_number is the sentinel 00607 // value of -1. If so, the sequence was not constrained by row number and 00608 // this method should never return true (which indicates that we're at the 00609 // end of a row-number constraint). If d_ending_row_number is not -1, then is 00610 // \e i at the end point? 6/1/2001 jhrg 00611 inline bool Sequence::is_end_of_rows(int i) 00612 { 00613 return ((d_ending_row_number == -1) ? false : (i > d_ending_row_number)); 00614 } 00615 00676 bool Sequence::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval) 00677 { 00678 DBG2(cerr << "Entering Sequence::serialize for " << name() << endl); 00679 00680 // Special case leaf sequences! 00681 bool status = false; 00682 00683 if (is_leaf_sequence()) 00684 status = serialize_leaf(dds, eval, m, ce_eval); 00685 else 00686 status = serialize_parent_part_one(dds, eval, m); 00687 00688 #ifdef CLEAR_LOCAL_DATA 00689 clear_local_data(); 00690 #endif 00691 00692 return status; 00693 } 00694 00695 // We know this is not a leaf Sequence. That means that this Sequence holds 00696 // another Sequence as one of its fields _and_ that child Sequence triggers 00697 // the actual transmission of values. 00698 00699 bool Sequence::serialize_parent_part_one(DDS &dds, ConstraintEvaluator &eval, Marshaller &m) 00700 { 00701 DBG2(cerr << "Entering serialize_parent_part_one for " << name() << endl); 00702 00703 int i = (d_starting_row_number != -1) ? d_starting_row_number : 0; 00704 00705 // read_row returns true if valid data was read, false if the EOF was 00706 // found. 6/1/2001 jhrg 00707 // Since this is a parent sequence, read the row ignoring the CE (all of 00708 // the CE clauses will be evaluated by the leaf sequence). 00709 bool status = read_row(i, dds, eval, false); 00710 DBG2(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00711 00712 while (status && !is_end_of_rows(i)) { 00713 i += d_row_stride; 00714 00715 // DBG(cerr << "Writing Start of Instance marker" << endl); 00716 // write_start_of_instance(sink); 00717 00718 // In this loop serialize will signal an error with an exception. 00719 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) { 00720 // Only call serialize for child Sequences; the leaf sequence 00721 // will trigger the transmission of values for its parents (this 00722 // sequence and maybe others) once it gets some valid data to 00723 // send. 00724 // Note that if the leaf sequence has no variables in the current 00725 // projection, its serialize() method will never be called and that's 00726 // the method that triggers actually sending values. Thus the leaf 00727 // sequence must be the lowest level sequence with values whose send_p 00728 // property is true. 00729 if ((*iter)->send_p() && (*iter)->type() == dods_sequence_c) (*iter)->serialize(eval, dds, m); 00730 } 00731 00732 set_read_p(false); // ...so this will read the next instance 00733 00734 status = read_row(i, dds, eval, false); 00735 DBG(cerr << "Sequence::serialize_parent_part_one::read_row() status: " << status << endl); 00736 } 00737 // Reset current row number for next nested sequence element. 00738 d_row_number = -1; 00739 00740 // Always write the EOS marker? 12/23/04 jhrg 00741 // Yes. According to DAP2, a completely empty response is signaled by 00742 // a return value of only the EOS marker for the outermost sequence. 00743 if (d_top_most || d_wrote_soi) { 00744 DBG(cerr << "Writing End of Sequence marker" << endl); 00745 write_end_of_sequence(m); 00746 d_wrote_soi = false; 00747 } 00748 00749 return true; // Signal errors with exceptions. 00750 } 00751 00752 // If we are here then we know that this is 'parent sequence' and that the 00753 // leaf sequence has found valid data to send. We also know that 00754 // serialize_parent_part_one has been called so data are in the instance's 00755 // fields. This is where we send data. Whereas ..._part_one() contains a 00756 // loop to iterate over all of rows in a parent sequence, this does not. This 00757 // method assumes that the serialize_leaf() will call it each time it needs 00758 // to be called. 00759 // 00760 // NB: This code only works if the child sequences appear after all other 00761 // variables. 00762 void Sequence::serialize_parent_part_two(DDS &dds, ConstraintEvaluator &eval, Marshaller &m) 00763 { 00764 DBG(cerr << "Entering serialize_parent_part_two for " << name() << endl); 00765 00766 BaseType *btp = get_parent(); 00767 if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m); 00768 00769 if (d_unsent_data) { 00770 DBG(cerr << "Writing Start of Instance marker" << endl); 00771 d_wrote_soi = true; 00772 write_start_of_instance(m); 00773 00774 // In this loop serialize will signal an error with an exception. 00775 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) { 00776 // Send all the non-sequence variables 00777 DBG(cerr << "Sequence::serialize_parent_part_two(), serializing " 00778 << (*iter)->name() << endl); 00779 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 00780 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00781 (*iter)->serialize(eval, dds, m, false); 00782 } 00783 } 00784 00785 d_unsent_data = false; // read should set this. 00786 } 00787 } 00788 00789 // This code is only run by a leaf sequence. Note that a one level sequence 00790 // is also a leaf sequence. 00791 bool Sequence::serialize_leaf(DDS &dds, ConstraintEvaluator &eval, Marshaller &m, bool ce_eval) 00792 { 00793 DBG(cerr << "Entering Sequence::serialize_leaf for " << name() << endl); 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 bool status = read_row(i, dds, eval, ce_eval); 00799 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00800 00801 // Once the first valid (satisfies the CE) row of the leaf sequence has 00802 // been read, we know we're going to send data. Send the current instance 00803 // of the parent/ancestor sequences now, if there are any. We only need 00804 // to do this once, hence it's not inside the while loop, but we only 00805 // send the parent seq data _if_ there's data in the leaf to send, that's 00806 // why we wait until after the first call to read_row() here in the leaf 00807 // sequence. 00808 // 00809 // NB: It's important to only call serialize_parent_part_two() for a 00810 // Sequence that really is the parent of a leaf sequence. 00811 if (status && !is_end_of_rows(i)) { 00812 BaseType *btp = get_parent(); 00813 if (btp && btp->type() == dods_sequence_c) static_cast<Sequence&>(*btp).serialize_parent_part_two(dds, eval, m); 00814 } 00815 00816 d_wrote_soi = false; 00817 while (status && !is_end_of_rows(i)) { 00818 i += d_row_stride; 00819 00820 DBG(cerr << "Writing Start of Instance marker" << endl); 00821 d_wrote_soi = true; 00822 write_start_of_instance(m); 00823 00824 // In this loop serialize will signal an error with an exception. 00825 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) { 00826 DBG(cerr << "Sequence::serialize_leaf(), serializing " 00827 << (*iter)->name() << endl); 00828 if ((*iter)->send_p()) { 00829 DBG(cerr << "Send P is true, sending " << (*iter)->name() << endl); 00830 (*iter)->serialize(eval, dds, m, false); 00831 } 00832 } 00833 00834 set_read_p(false); // ...so this will read the next instance 00835 00836 status = read_row(i, dds, eval, ce_eval); 00837 DBG(cerr << "Sequence::serialize_leaf::read_row() status: " << status << endl); 00838 } 00839 00840 // Only write the EOS marker if there's a matching Start Of Instance 00841 // Marker in the stream. 00842 if (d_wrote_soi || d_top_most) { 00843 DBG(cerr << "Writing End of Sequence marker" << endl); 00844 write_end_of_sequence(m); 00845 } 00846 00847 return true; // Signal errors with exceptions. 00848 } 00849 00872 void Sequence::intern_data(ConstraintEvaluator &eval, DDS &dds) 00873 { 00874 DBG(cerr << "Sequence::intern_data - for " << name() << endl); DBG2(cerr << " intern_data, values: " << &d_values << endl); 00875 00876 // Why use a stack instead of return values? We need the stack because 00877 // Sequences nested three of more levels deep will loose the middle 00878 // instances when the intern_data_parent_part_two() code is run. 00879 sequence_values_stack_t sequence_values_stack; 00880 00881 DBG2(cerr << " pushing d_values of " << name() << " (" << &d_values 00882 << ") on stack; size: " << sequence_values_stack.size() << endl); 00883 sequence_values_stack.push(&d_values); 00884 00885 intern_data_private(eval, dds, sequence_values_stack); 00886 } 00887 00888 void Sequence::intern_data_private(ConstraintEvaluator &eval, DDS &dds, sequence_values_stack_t &sequence_values_stack) 00889 { 00890 DBG(cerr << "Entering intern_data_private for " << name() << endl); 00891 00892 if (is_leaf_sequence()) 00893 intern_data_for_leaf(dds, eval, sequence_values_stack); 00894 else 00895 intern_data_parent_part_one(dds, eval, sequence_values_stack); 00896 } 00897 00898 void Sequence::intern_data_parent_part_one(DDS & dds, ConstraintEvaluator & eval, 00899 sequence_values_stack_t & sequence_values_stack) 00900 { 00901 DBG(cerr << "Entering intern_data_parent_part_one for " << name() << endl); 00902 00903 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 00904 00905 // read_row returns true if valid data was read, false if the EOF was 00906 // found. 6/1/2001 jhrg 00907 // Since this is a parent sequence, read the row ignoring the CE (all of 00908 // the CE clauses will be evaluated by the leaf sequence). 00909 bool status = read_row(i, dds, eval, false); 00910 00911 // Grab the current size of the value stack. We do this because it is 00912 // possible that no nested sequences for this row happened to be 00913 // selected because of a constraint evaluation or the last row is not 00914 // selected because of a constraint evaluation. In either case, no 00915 // nested sequence d_values are pushed onto the stack, so there is 00916 // nothing to pop at the end of this function. pcw 07/14/08 00917 SequenceValues::size_type orig_stack_size = sequence_values_stack.size(); 00918 00919 while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 00920 i += get_row_stride(); 00921 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 00922 if ((*iter)->send_p()) { 00923 switch ((*iter)->type()) { 00924 case dods_sequence_c: 00925 static_cast<Sequence&>(**iter).intern_data_private(eval, dds, sequence_values_stack); 00926 break; 00927 00928 default: 00929 (*iter)->intern_data(eval, dds); 00930 break; 00931 } 00932 } 00933 } 00934 00935 set_read_p(false); // ...so this will read the next instance 00936 00937 status = read_row(i, dds, eval, false); 00938 } 00939 00940 // Reset current row number for next nested sequence element. 00941 reset_row_number(); 00942 00943 // if the size of the stack is larger than the original size (retrieved 00944 // above) then pop the top set of d_values from the stack. If it's the 00945 // same, then no nested sequences, or possible the last nested sequence, 00946 // were pushed onto the stack, so there is nothing to pop. 00947 if (sequence_values_stack.size() > orig_stack_size) { 00948 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 00949 << ") off stack; size: " << sequence_values_stack.size() << endl); 00950 sequence_values_stack.pop(); 00951 } DBG(cerr << "Leaving intern_data_parent_part_one for " << name() << endl); 00952 } 00953 00954 void Sequence::intern_data_parent_part_two(DDS &dds, ConstraintEvaluator &eval, 00955 sequence_values_stack_t &sequence_values_stack) 00956 { 00957 DBG(cerr << "Entering intern_data_parent_part_two for " << name() << endl); 00958 00959 BaseType *btp = get_parent(); 00960 if (btp && btp->type() == dods_sequence_c) { 00961 static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack); 00962 } 00963 00964 DBG2(cerr << " stack size: " << sequence_values_stack.size() << endl); 00965 SequenceValues *values = sequence_values_stack.top(); 00966 DBG2(cerr << " using values = " << (void *)values << endl); 00967 00968 if (get_unsent_data()) { 00969 BaseTypeRow *row_data = new BaseTypeRow; 00970 00971 // In this loop transfer_data will signal an error with an exception. 00972 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 00973 00974 if ((*iter)->send_p() && (*iter)->type() != dods_sequence_c) { 00975 row_data->push_back((*iter)->ptr_duplicate()); 00976 } 00977 else if ((*iter)->send_p()) { //Sequence; must be the last variable 00978 Sequence *tmp = dynamic_cast<Sequence*>((*iter)->ptr_duplicate()); 00979 if (!tmp) { 00980 delete row_data; 00981 throw InternalErr(__FILE__, __LINE__, "Expected a Sequence."); 00982 } 00983 row_data->push_back(tmp); 00984 DBG2(cerr << " pushing d_values of " << tmp->name() 00985 << " (" << &(tmp->d_values) 00986 << ") on stack; size: " << sequence_values_stack.size() 00987 << endl); 00988 // This pushes the d_values field of the newly created leaf 00989 // Sequence onto the stack. The code then returns to intern 00990 // _data_for_leaf() where this value will be used. 00991 sequence_values_stack.push(&(tmp->d_values)); 00992 } 00993 } 00994 00995 DBG2(cerr << " pushing values for " << name() 00996 << " to " << values << endl); 00997 values->push_back(row_data); 00998 set_unsent_data(false); 00999 } DBG(cerr << "Leaving intern_data_parent_part_two for " << name() << endl); 01000 } 01001 01002 void Sequence::intern_data_for_leaf(DDS &dds, ConstraintEvaluator &eval, sequence_values_stack_t &sequence_values_stack) 01003 { 01004 DBG(cerr << "Entering intern_data_for_leaf for " << name() << endl); 01005 01006 int i = (get_starting_row_number() != -1) ? get_starting_row_number() : 0; 01007 01008 DBG2(cerr << " reading row " << i << endl); 01009 bool status = read_row(i, dds, eval, true); 01010 DBG2(cerr << " status: " << status << endl); DBG2(cerr << " ending row number: " << get_ending_row_number() << endl); 01011 01012 if (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 01013 BaseType *btp = get_parent(); 01014 if (btp && btp->type() == dods_sequence_c) { 01015 // This call will read the values for the parent sequences and 01016 // then allocate a new instance for the leaf and push that onto 01017 // the stack. 01018 static_cast<Sequence&>(*btp).intern_data_parent_part_two(dds, eval, sequence_values_stack); 01019 } 01020 01021 // intern_data_parent_part_two pushes the d_values field of the leaf 01022 // onto the stack, so this operation grabs that value and then loads 01023 // data into it. 01024 SequenceValues *values = sequence_values_stack.top(); 01025 DBG2(cerr << " using values = " << values << endl); 01026 01027 while (status && (get_ending_row_number() == -1 || i <= get_ending_row_number())) { 01028 i += get_row_stride(); 01029 01030 // Copy data from the object's fields to this new BaeTypeRow instance 01031 BaseTypeRow *row_data = new BaseTypeRow; 01032 for (Vars_iter iter = var_begin(); iter != var_end(); iter++) { 01033 if ((*iter)->send_p()) { 01034 row_data->push_back((*iter)->ptr_duplicate()); 01035 } 01036 } 01037 01038 DBG2(cerr << " pushing values for " << name() 01039 << " to " << values << endl); 01040 // Save the row_data to values(). 01041 values->push_back(row_data); 01042 01043 set_read_p(false); // ...so this will read the next instance 01044 // Read the ith row into this object's fields 01045 status = read_row(i, dds, eval, true); 01046 } 01047 01048 DBG2(cerr << " popping d_values (" << sequence_values_stack.top() 01049 << ") off stack; size: " << sequence_values_stack.size() << endl); 01050 sequence_values_stack.pop(); 01051 } DBG(cerr << "Leaving intern_data_for_leaf for " << name() << endl); 01052 } 01053 01074 bool Sequence::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 01075 { 01076 DataDDS *dd = dynamic_cast<DataDDS *>(dds); 01077 if (!dd) throw InternalErr("Expected argument 'dds' to be a DataDDS!"); 01078 01079 DBG2(cerr << "Reading from server/protocol version: " 01080 << dd->get_protocol_major() << "." << dd->get_protocol_minor() 01081 << endl); 01082 01083 // Check for old servers. 01084 if (dd->get_protocol_major() < 2) { 01085 throw Error( 01086 string("The protocl version (") + dd->get_protocol() 01087 + ") indicates that this\nis an old server which may not correctly transmit Sequence variables.\nContact the server administrator."); 01088 } 01089 01090 while (true) { 01091 // Grab the sequence stream's marker. 01092 unsigned char marker = read_marker(um); 01093 if (is_end_of_sequence(marker)) 01094 break; // EXIT the while loop here!!! 01095 else if (is_start_of_instance(marker)) { 01096 d_row_number++; 01097 DBG2(cerr << "Reading row " << d_row_number << " of " 01098 << name() << endl); 01099 BaseTypeRow *bt_row_ptr = new BaseTypeRow; 01100 // Read the instance's values, building up the row 01101 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) { 01102 BaseType *bt_ptr = (*iter)->ptr_duplicate(); 01103 bt_ptr->deserialize(um, dds, reuse); 01104 DBG2(cerr << "Deserialized " << bt_ptr->name() << " (" 01105 << bt_ptr << ") = "); DBG2(bt_ptr->print_val(stderr, "")); 01106 bt_row_ptr->push_back(bt_ptr); 01107 } 01108 // Append this row to those accumulated. 01109 d_values.push_back(bt_row_ptr); 01110 } 01111 else 01112 throw Error("I could not read the expected Sequence data stream marker!"); 01113 }; 01114 01115 return false; 01116 } 01117 01118 // Return the current row number. 01119 01131 int Sequence::get_starting_row_number() 01132 { 01133 return d_starting_row_number; 01134 } 01135 01146 int Sequence::get_row_stride() 01147 { 01148 return d_row_stride; 01149 } 01150 01162 int Sequence::get_ending_row_number() 01163 { 01164 return d_ending_row_number; 01165 } 01166 01175 void Sequence::set_row_number_constraint(int start, int stop, int stride) 01176 { 01177 if (stop < start) throw Error(malformed_expr, "Starting row number must precede the ending row number."); 01178 01179 d_starting_row_number = start; 01180 d_row_stride = stride; 01181 d_ending_row_number = stop; 01182 } 01183 01184 void Sequence::print_one_row(FILE *out, int row, string space, bool print_row_num) 01185 { 01186 ostringstream oss; 01187 print_one_row(oss, row, space, print_row_num); 01188 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 01189 } 01190 01191 void Sequence::print_one_row(ostream &out, int row, string space, bool print_row_num) 01192 { 01193 if (print_row_num) out << "\n" << space << row << ": "; 01194 01195 out << "{ "; 01196 01197 int elements = element_count(); 01198 int j = 0; 01199 BaseType *bt_ptr = 0; 01200 01201 // This version of print_one_row() works for both data read with 01202 // deserialize(), where each variable is assumed to have valid data, and 01203 // intern_data(), where some/many variables do not. Because of that, it's 01204 // not correct to assume that all of the elements will be printed, which 01205 // is what the old code did. 01206 // Print the first value 01207 while (j < elements && !bt_ptr) { 01208 bt_ptr = var_value(row, j++); 01209 if (bt_ptr) { // data 01210 if (bt_ptr->type() == dods_sequence_c) 01211 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num); 01212 else 01213 bt_ptr->print_val(out, space, false); 01214 } 01215 } 01216 01217 // Print the remaining values 01218 while (j < elements) { 01219 bt_ptr = var_value(row, j++); 01220 if (bt_ptr) { // data 01221 out << ", "; 01222 if (bt_ptr->type() == dods_sequence_c) 01223 static_cast<Sequence*>(bt_ptr)->print_val_by_rows(out, space + " ", false, print_row_num); 01224 else 01225 bt_ptr->print_val(out, space, false); 01226 } 01227 } 01228 01229 out << " }"; 01230 } 01231 01232 void Sequence::print_val_by_rows(FILE *out, string space, bool print_decl_p, bool print_row_numbers) 01233 { 01234 ostringstream oss; 01235 print_val_by_rows(oss, space, print_decl_p, print_row_numbers); 01236 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 01237 } 01238 01239 void Sequence::print_val_by_rows(ostream &out, string space, bool print_decl_p, bool print_row_numbers) 01240 { 01241 if (print_decl_p) { 01242 print_decl(out, space, false); 01243 out << " = "; 01244 } 01245 01246 out << "{ "; 01247 01248 int rows = number_of_rows() - 1; 01249 int i; 01250 for (i = 0; i < rows; ++i) { 01251 print_one_row(out, i, space, print_row_numbers); 01252 out << ", "; 01253 } 01254 print_one_row(out, i, space, print_row_numbers); 01255 01256 out << " }"; 01257 01258 if (print_decl_p) out << ";\n"; 01259 } 01260 01261 void Sequence::print_val(FILE *out, string space, bool print_decl_p) 01262 { 01263 print_val_by_rows(out, space, print_decl_p, false); 01264 } 01265 01266 void Sequence::print_val(ostream &out, string space, bool print_decl_p) 01267 { 01268 print_val_by_rows(out, space, print_decl_p, false); 01269 } 01270 01271 void Sequence::set_leaf_p(bool state) 01272 { 01273 d_leaf_sequence = state; 01274 } 01275 01276 bool Sequence::is_leaf_sequence() 01277 { 01278 return d_leaf_sequence; 01279 } 01280 01305 void Sequence::set_leaf_sequence(int lvl) 01306 { 01307 bool has_child_sequence = false; 01308 01309 if (lvl == 1) d_top_most = true; 01310 01311 DBG2(cerr << "Processing sequence " << name() << endl); 01312 01313 for (Vars_iter iter = d_vars.begin(); iter != d_vars.end(); iter++) { 01314 // About the test for send_p(): Only descend into a sequence if it has 01315 // fields that might be sent. Thus if, in a two-level sequence, nothing 01316 // in the lower level is to be sent, the upper level is marked as the 01317 // leaf sequence. This ensures that values _will_ be sent (see the comment 01318 // in serialize_leaf() and serialize_parent_part_one()). 01319 if ((*iter)->type() == dods_sequence_c && (*iter)->send_p()) { 01320 if (has_child_sequence) 01321 throw Error("This implementation does not support more than one nested sequence at a level. Contact the server administrator."); 01322 01323 has_child_sequence = true; 01324 static_cast<Sequence&>(**iter).set_leaf_sequence(++lvl); 01325 } 01326 else if ((*iter)->type() == dods_structure_c) { 01327 static_cast<Structure&>(**iter).set_leaf_sequence(lvl); 01328 } 01329 } 01330 01331 if (!has_child_sequence) 01332 set_leaf_p(true); 01333 else 01334 set_leaf_p(false); 01335 01336 DBG2(cerr << "is_leaf_sequence(): " << is_leaf_sequence() << " (" << name() << ")" << endl); 01337 } 01338 01347 void Sequence::dump(ostream &strm) const 01348 { 01349 strm << DapIndent::LMarg << "Sequence::dump - (" << (void *) this << ")" << endl; 01350 DapIndent::Indent(); 01351 Constructor::dump(strm); 01352 strm << DapIndent::LMarg << "# rows deserialized: " << d_row_number << endl; 01353 strm << DapIndent::LMarg << "bracket notation information:" << endl; 01354 DapIndent::Indent(); 01355 strm << DapIndent::LMarg << "starting row #: " << d_starting_row_number << endl; 01356 strm << DapIndent::LMarg << "row stride: " << d_row_stride << endl; 01357 strm << DapIndent::LMarg << "ending row #: " << d_ending_row_number << endl; 01358 DapIndent::UnIndent(); 01359 01360 strm << DapIndent::LMarg << "data been sent? " << d_unsent_data << endl; 01361 strm << DapIndent::LMarg << "start of instance? " << d_wrote_soi << endl; 01362 strm << DapIndent::LMarg << "is leaf sequence? " << d_leaf_sequence << endl; 01363 strm << DapIndent::LMarg << "top most in hierarchy? " << d_top_most << endl; 01364 DapIndent::UnIndent(); 01365 } 01366 01367 } // namespace libdap 01368