libdap
Updated for version 3.17.0
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1995-1999 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 00033 #include "config.h" 00034 00035 #include <string> 00036 #include <sstream> 00037 #include <algorithm> 00038 #include <functional> 00039 00040 #include <stdint.h> 00041 00042 //#define DODS_DEBUG 00043 00044 #include "crc.h" 00045 00046 #include "Constructor.h" 00047 #include "Grid.h" 00048 00049 #include "DMR.h" 00050 #include "XMLWriter.h" 00051 #include "D4StreamMarshaller.h" 00052 #include "D4StreamUnMarshaller.h" 00053 00054 #include "D4Attributes.h" 00055 00056 #include "debug.h" 00057 #include "escaping.h" 00058 #include "util.h" 00059 #include "Error.h" 00060 #include "InternalErr.h" 00061 00062 using namespace std; 00063 00064 namespace libdap { 00065 00066 // Private member functions 00067 00068 void 00069 Constructor::m_duplicate(const Constructor &c) 00070 { 00071 DBG(cerr << "In Constructor::m_duplicate for " << c.name() << endl); 00072 // Clear out any spurious vars in Constructor::d_vars 00073 // Moved from Grid::m_duplicate. jhrg 4/3/13 00074 d_vars.clear(); // [mjohnson 10 Sep 2009] 00075 00076 Vars_citer i = c.d_vars.begin(); 00077 while (i != c.d_vars.end()) { 00078 BaseType *btp = (*i++)->ptr_duplicate(); 00079 btp->set_parent(this); 00080 d_vars.push_back(btp); 00081 } 00082 00083 DBG(cerr << "Exiting Constructor::m_duplicate for " << c.name() << endl); 00084 } 00085 00086 // Public member functions 00087 00088 Constructor::Constructor(const string &name, const Type &type, bool is_dap4) 00089 : BaseType(name, type, is_dap4) 00090 {} 00091 00102 Constructor::Constructor(const string &name, const string &dataset, const Type &type, bool is_dap4) 00103 : BaseType(name, dataset, type, is_dap4) 00104 {} 00105 00106 Constructor::Constructor(const Constructor &rhs) : BaseType(rhs), d_vars(0) 00107 { 00108 DBG(cerr << "In Constructor::copy_ctor for " << rhs.name() << endl); 00109 m_duplicate(rhs); 00110 } 00111 00112 Constructor::~Constructor() 00113 { 00114 Vars_iter i = d_vars.begin(); 00115 while (i != d_vars.end()) { 00116 delete *i++; 00117 } 00118 } 00119 00120 Constructor & 00121 Constructor::operator=(const Constructor &rhs) 00122 { 00123 DBG(cerr << "Entering Constructor::operator=" << endl); 00124 if (this == &rhs) 00125 return *this; 00126 00127 dynamic_cast<BaseType &>(*this) = rhs; // run BaseType= 00128 00129 m_duplicate(rhs); 00130 00131 DBG(cerr << "Exiting Constructor::operator=" << endl); 00132 return *this; 00133 } 00134 00135 // A public method, but just barely.. 00136 BaseType * 00137 Constructor::transform_to_dap4(D4Group *root, Constructor *dest) 00138 { 00139 for (Constructor::Vars_citer i = var_begin(), e = var_end(); i != e; ++i) { 00140 BaseType *new_var = (*i)->transform_to_dap4(root, dest); 00141 if (new_var) { // Might be a Grid; see the comment in BaseType::transform_to_dap4() 00142 new_var->set_parent(dest); 00143 dest->add_var_nocopy(new_var); 00144 } 00145 } 00146 00147 // Add attributes 00148 dest->attributes()->transform_to_dap4(get_attr_table()); 00149 00150 dest->set_is_dap4(true); 00151 00152 return dest; 00153 } 00154 00155 string 00156 Constructor::FQN() const 00157 { 00158 if (get_parent() == 0) 00159 return name(); 00160 else if (get_parent()->type() == dods_group_c) 00161 return get_parent()->FQN() + name(); 00162 else if (get_parent()->type() == dods_array_c) 00163 return get_parent()->FQN(); 00164 else 00165 return get_parent()->FQN() + "." + name(); 00166 } 00167 00168 int 00169 Constructor::element_count(bool leaves) 00170 { 00171 if (!leaves) 00172 return d_vars.size(); 00173 else { 00174 int i = 0; 00175 for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) { 00176 i += (*j)->element_count(leaves); 00177 } 00178 return i; 00179 } 00180 } 00181 00182 void 00183 Constructor::set_send_p(bool state) 00184 { 00185 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00186 (*i)->set_send_p(state); 00187 } 00188 00189 BaseType::set_send_p(state); 00190 } 00191 00192 void 00193 Constructor::set_read_p(bool state) 00194 { 00195 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00196 (*i)->set_read_p(state); 00197 } 00198 00199 BaseType::set_read_p(state); 00200 } 00201 00202 #if 0 00203 // TODO Recode to use width(bool). Bur see comments in BaseType.h 00204 unsigned int 00205 Constructor::width() 00206 { 00207 unsigned int sz = 0; 00208 00209 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00210 sz += (*i)->width(); 00211 } 00212 00213 return sz; 00214 } 00215 #endif 00216 00223 unsigned int 00224 Constructor::width(bool constrained) const 00225 { 00226 unsigned int sz = 0; 00227 00228 for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) { 00229 if (constrained) { 00230 if ((*i)->send_p()) 00231 sz += (*i)->width(constrained); 00232 } 00233 else { 00234 sz += (*i)->width(constrained); 00235 } 00236 } 00237 00238 return sz; 00239 } 00240 00241 BaseType * 00242 Constructor::var(const string &name, bool exact_match, btp_stack *s) 00243 { 00244 string n = www2id(name); 00245 00246 if (exact_match) 00247 return m_exact_match(n, s); 00248 else 00249 return m_leaf_match(n, s); 00250 } 00251 00253 BaseType * 00254 Constructor::var(const string &n, btp_stack &s) 00255 { 00256 // This should probably be removed. The BES code should remove web encoding 00257 // with the possible exception of spaces. jhrg 11/25/13 00258 string name = www2id(n); 00259 00260 BaseType *btp = m_exact_match(name, &s); 00261 if (btp) 00262 return btp; 00263 00264 return m_leaf_match(name, &s); 00265 } 00266 00267 // Protected method 00268 BaseType * 00269 Constructor::m_leaf_match(const string &name, btp_stack *s) 00270 { 00271 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00272 if ((*i)->name() == name) { 00273 if (s) { 00274 DBG(cerr << "Pushing " << this->name() << endl); 00275 s->push(static_cast<BaseType *>(this)); 00276 } 00277 return *i; 00278 } 00279 if ((*i)->is_constructor_type()) { 00280 BaseType *btp = (*i)->var(name, false, s); 00281 if (btp) { 00282 if (s) { 00283 DBG(cerr << "Pushing " << this->name() << endl); 00284 s->push(static_cast<BaseType *>(this)); 00285 } 00286 return btp; 00287 } 00288 } 00289 } 00290 00291 return 0; 00292 } 00293 00294 // Protected method 00295 BaseType * 00296 Constructor::m_exact_match(const string &name, btp_stack *s) 00297 { 00298 // Look for name at the top level first. 00299 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00300 if ((*i)->name() == name) { 00301 if (s) 00302 s->push(static_cast<BaseType *>(this)); 00303 00304 return *i; 00305 } 00306 } 00307 00308 // If it was not found using the simple search, look for a dot and 00309 // search the hierarchy. 00310 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00311 if (dot_pos != string::npos) { 00312 string aggregate = name.substr(0, dot_pos); 00313 string field = name.substr(dot_pos + 1); 00314 00315 BaseType *agg_ptr = var(aggregate); 00316 if (agg_ptr) { 00317 if (s) 00318 s->push(static_cast<BaseType *>(this)); 00319 00320 return agg_ptr->var(field, true, s); // recurse 00321 } 00322 else 00323 return 0; // qualified names must be *fully* qualified 00324 } 00325 00326 return 0; 00327 } 00328 00330 Constructor::Vars_iter 00331 Constructor::var_begin() 00332 { 00333 return d_vars.begin() ; 00334 } 00335 00338 Constructor::Vars_iter 00339 Constructor::var_end() 00340 { 00341 return d_vars.end() ; 00342 } 00343 00345 Constructor::Vars_riter 00346 Constructor::var_rbegin() 00347 { 00348 return d_vars.rbegin(); 00349 } 00350 00353 Constructor::Vars_riter 00354 Constructor::var_rend() 00355 { 00356 return d_vars.rend(); 00357 } 00358 00362 Constructor::Vars_iter 00363 Constructor::get_vars_iter(int i) 00364 { 00365 return d_vars.begin() + i; 00366 } 00367 00371 BaseType * 00372 Constructor::get_var_index(int i) 00373 { 00374 return *(d_vars.begin() + i); 00375 } 00376 00381 void 00382 Constructor::add_var(BaseType *bt, Part) 00383 { 00384 // Jose Garcia 00385 // Passing and invalid pointer to an object is a developer's error. 00386 if (!bt) 00387 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null."); 00388 #if 0 00389 if (bt->is_dap4_only_type()) 00390 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure."); 00391 #endif 00392 // Jose Garcia 00393 // Now we add a copy of bt so the external user is able to destroy bt as 00394 // he/she wishes. The policy is: "If it is allocated outside, it is 00395 // deallocated outside, if it is allocated inside, it is deallocated 00396 // inside" 00397 BaseType *btp = bt->ptr_duplicate(); 00398 btp->set_parent(this); 00399 d_vars.push_back(btp); 00400 } 00401 00406 void 00407 Constructor::add_var_nocopy(BaseType *bt, Part) 00408 { 00409 if (!bt) 00410 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null."); 00411 #if 0 00412 if (bt->is_dap4_only_type()) 00413 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure."); 00414 #endif 00415 bt->set_parent(this); 00416 d_vars.push_back(bt); 00417 } 00418 00422 void 00423 Constructor::del_var(const string &n) 00424 { 00425 // TODO remove_if? find_if? 00426 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00427 if ((*i)->name() == n) { 00428 BaseType *bt = *i ; 00429 d_vars.erase(i) ; 00430 delete bt ; bt = 0; 00431 return; 00432 } 00433 } 00434 } 00435 00436 void 00437 Constructor::del_var(Vars_iter i) 00438 { 00439 if (*i != 0) { 00440 BaseType *bt = *i; 00441 d_vars.erase(i); 00442 delete bt; 00443 } 00444 } 00445 00451 bool Constructor::read() 00452 { 00453 DBG(cerr << "Entering Constructor::read..." << endl); 00454 if (!read_p()) { 00455 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00456 (*i)->read(); 00457 } 00458 set_read_p(true); 00459 } 00460 00461 return false; 00462 } 00463 00464 void 00465 Constructor::intern_data(ConstraintEvaluator & eval, DDS & dds) 00466 { 00467 DBG(cerr << "Constructor::intern_data: " << name() << endl); 00468 if (!read_p()) 00469 read(); // read() throws Error and InternalErr 00470 00471 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00472 if ((*i)->send_p()) { 00473 (*i)->intern_data(eval, dds); 00474 } 00475 } 00476 } 00477 00478 bool 00479 Constructor::serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval) 00480 { 00481 #if USE_LOCAL_TIMEOUT_SCHEME 00482 dds.timeout_on(); 00483 #endif 00484 if (!read_p()) 00485 read(); // read() throws Error and InternalErr 00486 00487 if (ce_eval && !eval.eval_selection(dds, dataset())) 00488 return true; 00489 #if USE_LOCAL_TIMEOUT_SCHEME 00490 dds.timeout_off(); 00491 #endif 00492 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00493 if ((*i)->send_p()) { 00494 #ifdef CHECKSUMS 00495 XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m); 00496 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c) 00497 sm->reset_checksum(); 00498 00499 (*i)->serialize(eval, dds, m, false); 00500 00501 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c) 00502 sm->get_checksum(); 00503 #else 00504 // (*i)->serialize(eval, dds, m, false); 00505 // Only Sequence and Vector run the evaluator. 00506 (*i)->serialize(eval, dds, m, true); 00507 #endif 00508 } 00509 } 00510 00511 return true; 00512 } 00513 00514 bool 00515 Constructor::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00516 { 00517 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00518 (*i)->deserialize(um, dds, reuse); 00519 } 00520 00521 return false; 00522 } 00523 00524 void 00525 Constructor::compute_checksum(Crc32 &) 00526 { 00527 throw InternalErr(__FILE__, __LINE__, "Computing a checksum alone is not supported for Constructor types."); 00528 } 00529 00530 void 00531 Constructor::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator & eval*/) 00532 { 00533 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00534 if ((*i)->send_p()) { 00535 (*i)->intern_data(/*checksum, dmr, eval*/); 00536 } 00537 } 00538 } 00539 00540 00552 void 00553 Constructor::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter) 00554 { 00555 #if 1 00556 // Not used for the same reason the equivalent code in D4Group::serialize() 00557 // is not used. Fail for D4Sequence and general issues with memory use. 00558 // 00559 // Revisit this - I had to uncomment this to get the netcdf_handler code 00560 // to work - it relies on having NCStructure::read() called. The D4Sequence 00561 // ::serialize() method calls read_next_instance(). What seems to be happening 00562 // is that this call to read gets the first set of values, but does not store 00563 // them; the call to serialize then runs the D4Sequence::serialize() method that 00564 // _does_ read all of the sequence data and then serialize it. However, the first 00565 // sequence instance is missing... 00566 if (!read_p()) 00567 read(); // read() throws Error 00568 #endif 00569 #if 0 00570 // place holder for now. There may be no need for this; only Array and Seq? 00571 // jhrg 9/6/13 00572 if (filter && !eval.eval_selection(dmr, dataset())) 00573 return true; 00574 #endif 00575 00576 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00577 if ((*i)->send_p()) { 00578 (*i)->serialize(m, dmr, /*eval,*/ filter); 00579 } 00580 } 00581 } 00582 00583 void 00584 Constructor::deserialize(D4StreamUnMarshaller &um, DMR &dmr) 00585 { 00586 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00587 (*i)->deserialize(um, dmr); 00588 } 00589 } 00590 00591 void 00592 Constructor::print_decl(FILE *out, string space, bool print_semi, 00593 bool constraint_info, bool constrained) 00594 { 00595 ostringstream oss; 00596 print_decl(oss, space, print_semi, constraint_info, constrained); 00597 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 00598 } 00599 00600 void 00601 Constructor::print_decl(ostream &out, string space, bool print_semi, 00602 bool constraint_info, bool constrained) 00603 { 00604 if (constrained && !send_p()) 00605 return; 00606 00607 out << space << type_name() << " {\n" ; 00608 for (Vars_citer i = d_vars.begin(); i != d_vars.end(); i++) { 00609 (*i)->print_decl(out, space + " ", true, constraint_info, constrained); 00610 } 00611 out << space << "} " << id2www(name()) ; 00612 00613 if (constraint_info) { // Used by test drivers only. 00614 if (send_p()) 00615 out << ": Send True"; 00616 else 00617 out << ": Send False"; 00618 } 00619 00620 if (print_semi) 00621 out << ";\n" ; 00622 } 00623 00624 void 00625 Constructor::print_val(FILE *out, string space, bool print_decl_p) 00626 { 00627 ostringstream oss; 00628 print_val(oss, space, print_decl_p); 00629 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 00630 } 00631 00632 void 00633 Constructor::print_val(ostream &out, string space, bool print_decl_p) 00634 { 00635 if (print_decl_p) { 00636 print_decl(out, space, false); 00637 out << " = " ; 00638 } 00639 00640 out << "{ " ; 00641 for (Vars_citer i = d_vars.begin(); i != d_vars.end(); 00642 i++, (void)(i != d_vars.end() && out << ", ")) { 00643 (*i)->print_val(out, "", false); 00644 } 00645 00646 out << " }" ; 00647 00648 if (print_decl_p) 00649 out << ";\n" ; 00650 } 00651 00655 void 00656 Constructor::print_xml(FILE *out, string space, bool constrained) 00657 { 00658 XMLWriter xml(space); 00659 print_xml_writer(xml, constrained); 00660 fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out); 00661 } 00662 00666 void 00667 Constructor::print_xml(ostream &out, string space, bool constrained) 00668 { 00669 XMLWriter xml(space); 00670 print_xml_writer(xml, constrained); 00671 out << xml.get_doc(); 00672 } 00673 00674 class PrintFieldXMLWriter : public unary_function<BaseType *, void> 00675 { 00676 XMLWriter &d_xml; 00677 bool d_constrained; 00678 public: 00679 PrintFieldXMLWriter(XMLWriter &x, bool c) 00680 : d_xml(x), d_constrained(c) 00681 {} 00682 00683 void operator()(BaseType *btp) 00684 { 00685 btp->print_xml_writer(d_xml, d_constrained); 00686 } 00687 }; 00688 00689 void 00690 Constructor::print_xml_writer(XMLWriter &xml, bool constrained) 00691 { 00692 if (constrained && !send_p()) 00693 return; 00694 00695 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0) 00696 throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element"); 00697 00698 if (!name().empty()) 00699 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0) 00700 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name"); 00701 00702 // DAP2 prints attributes first. For some reason we decided that DAP4 should 00703 // print them second. No idea why... jhrg 8/15/14 00704 if (!is_dap4() && get_attr_table().get_size() > 0) 00705 get_attr_table().print_xml_writer(xml); 00706 00707 bool has_variables = (var_begin() != var_end()); 00708 if (has_variables) 00709 for_each(var_begin(), var_end(), PrintFieldXMLWriter(xml, constrained)); 00710 00711 if (is_dap4()) 00712 attributes()->print_dap4(xml); 00713 00714 #if 0 00715 // Moved up above so that the DDX tests for various handles will still work. 00716 // jhrg 8/15/14 00717 if (!is_dap4() && get_attr_table().get_size() > 0) 00718 get_attr_table().print_xml_writer(xml); 00719 #endif 00720 00721 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00722 throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element"); 00723 } 00724 00725 class PrintDAP4FieldXMLWriter : public unary_function<BaseType *, void> 00726 { 00727 XMLWriter &d_xml; 00728 bool d_constrained; 00729 public: 00730 PrintDAP4FieldXMLWriter(XMLWriter &x, bool c) : d_xml(x), d_constrained(c) {} 00731 00732 void operator()(BaseType *btp) 00733 { 00734 btp->print_dap4(d_xml, d_constrained); 00735 } 00736 }; 00737 00738 00739 void 00740 Constructor::print_dap4(XMLWriter &xml, bool constrained) 00741 { 00742 if (constrained && !send_p()) 00743 return; 00744 00745 if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0) 00746 throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element"); 00747 00748 if (!name().empty()) 00749 if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0) 00750 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name"); 00751 00752 bool has_variables = (var_begin() != var_end()); 00753 if (has_variables) 00754 for_each(var_begin(), var_end(), PrintDAP4FieldXMLWriter(xml, constrained)); 00755 00756 attributes()->print_dap4(xml); 00757 00758 if (xmlTextWriterEndElement(xml.get_writer()) < 0) 00759 throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element"); 00760 } 00761 00762 00763 bool 00764 Constructor::check_semantics(string &msg, bool all) 00765 { 00766 if (!BaseType::check_semantics(msg)) 00767 return false; 00768 00769 if (!unique_names(d_vars, name(), type_name(), msg)) 00770 return false; 00771 00772 if (all) 00773 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00774 if (!(*i)->check_semantics(msg, true)) { 00775 return false; 00776 } 00777 } 00778 00779 return true; 00780 } 00781 00794 bool 00795 Constructor::is_linear() 00796 { 00797 return false; 00798 } 00799 00805 void 00806 Constructor::set_in_selection(bool state) 00807 { 00808 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00809 (*i)->set_in_selection(state); 00810 } 00811 00812 BaseType::set_in_selection(state); 00813 } 00814 00823 void 00824 Constructor::dump(ostream &strm) const 00825 { 00826 strm << DapIndent::LMarg << "Constructor::dump - (" 00827 << (void *)this << ")" << endl ; 00828 DapIndent::Indent() ; 00829 BaseType::dump(strm) ; 00830 strm << DapIndent::LMarg << "vars: " << endl ; 00831 DapIndent::Indent() ; 00832 Vars_citer i = d_vars.begin() ; 00833 Vars_citer ie = d_vars.end() ; 00834 for (; i != ie; i++) { 00835 (*i)->dump(strm) ; 00836 } 00837 DapIndent::UnIndent() ; 00838 DapIndent::UnIndent() ; 00839 } 00840 00841 } // namespace libdap 00842