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 1994-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 // Implementation for the class Structure 00033 // 00034 // jhrg 9/14/94 00035 00036 //#define DODS_DEBUG 00037 00038 #include "config.h" 00039 00040 #include <sstream> 00041 00042 #include "Byte.h" 00043 #include "Int16.h" 00044 #include "UInt16.h" 00045 #include "Int32.h" 00046 #include "UInt32.h" 00047 #include "Float32.h" 00048 #include "Float64.h" 00049 #include "Str.h" 00050 #include "Url.h" 00051 #include "Array.h" 00052 #include "Structure.h" 00053 #include "Sequence.h" 00054 #include "Grid.h" 00055 00056 #include "DDS.h" 00057 #include "ConstraintEvaluator.h" 00058 00059 #include "D4Attributes.h" 00060 #include "D4Group.h" 00061 00062 #include "XDRStreamMarshaller.h" 00063 #include "util.h" 00064 #include "debug.h" 00065 #include "InternalErr.h" 00066 #include "escaping.h" 00067 00068 using std::cerr; 00069 using std::endl; 00070 00071 namespace libdap { 00072 00073 #if 0 00074 00078 void 00079 Structure::m_duplicate(const Structure &s) 00080 { 00081 Constructor::m_duplicate(s); 00082 #if 0 00083 Structure &cs = const_cast<Structure &>(s); 00084 00085 DBG(cerr << "Copying structure: " << name() << endl); 00086 00087 for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) { 00088 DBG(cerr << "Copying field: " << (*i)->name() << endl); 00089 // Jose Garcia 00090 // I think this assert here is part of a debugging 00091 // process since it is going along with a DBG call 00092 // I leave it here since it can be remove by defining NDEBUG. 00093 // assert(*i); 00094 BaseType *btp = (*i)->ptr_duplicate(); 00095 btp->set_parent(this); 00096 d_vars.push_back(btp); 00097 } 00098 #endif 00099 } 00100 #endif 00101 00109 Structure::Structure(const string &n) : Constructor(n, dods_structure_c) 00110 {} 00111 00121 Structure::Structure(const string &n, const string &d) 00122 : Constructor(n, d, dods_structure_c) 00123 {} 00124 00126 Structure::Structure(const Structure &rhs) : Constructor(rhs) 00127 { 00128 DBG(cerr << "In Structure::copy_ctor for " << name() << endl); 00129 //m_duplicate(rhs); 00130 } 00131 00132 Structure::~Structure() 00133 { 00134 } 00135 00136 BaseType * 00137 Structure::ptr_duplicate() 00138 { 00139 return new Structure(*this); 00140 } 00141 00151 BaseType * 00152 Structure::transform_to_dap4(D4Group *root, Constructor *container) 00153 { 00154 // For this class, ptr_duplicate() calls the const ctor which calls 00155 // Constructor's const ctor which calls Constructor::m_duplicate(). 00156 // Here we replicate some of that functionality, but instead call 00157 // transform_to_dap4() on the contained variables. 00158 00159 // Structure *dest = static_cast<Structure*>(ptr_duplicate()); 00160 Structure *dest = new Structure(name()); 00161 00162 Constructor::transform_to_dap4(root, dest); 00163 dest->set_parent(container); 00164 00165 return dest; 00166 } 00167 00168 Structure & 00169 Structure::operator=(const Structure &rhs) 00170 { 00171 DBG(cerr << "Entering Structure::operator=" << endl); 00172 if (this == &rhs) 00173 return *this; 00174 00175 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00176 00177 //m_duplicate(rhs); 00178 00179 DBG(cerr << "Exiting Structure::operator=" << endl); 00180 return *this; 00181 } 00182 00183 #if 0 00184 int 00185 Structure::element_count(bool leaves) 00186 { 00187 if (!leaves) 00188 return d_vars.size(); 00189 else { 00190 int i = 0; 00191 for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) { 00192 i += (*j)->element_count(leaves); 00193 } 00194 return i; 00195 } 00196 } 00197 #endif 00198 00199 bool 00200 Structure::is_linear() 00201 { 00202 bool linear = true; 00203 for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) { 00204 if ((*i)->type() == dods_structure_c) 00205 linear = linear && static_cast<Structure*>((*i))->is_linear(); 00206 else 00207 linear = linear && (*i)->is_simple_type(); 00208 } 00209 00210 return linear; 00211 } 00212 00213 #if 0 00214 void 00215 Structure::set_send_p(bool state) 00216 { 00217 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00218 (*i)->set_send_p(state); 00219 } 00220 00221 BaseType::set_send_p(state); 00222 } 00223 00224 void 00225 Structure::set_read_p(bool state) 00226 { 00227 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00228 (*i)->set_read_p(state); 00229 } 00230 00231 BaseType::set_read_p(state); 00232 } 00233 #endif 00234 #if 0 00235 00240 void 00241 Structure::set_in_selection(bool state) 00242 { 00243 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00244 (*i)->set_in_selection(state); 00245 } 00246 00247 BaseType::set_in_selection(state); 00248 } 00249 #endif 00250 00251 void 00252 Structure::set_leaf_sequence(int level) 00253 { 00254 for (Vars_iter i = var_begin(); i != var_end(); i++) { 00255 if ((*i)->type() == dods_sequence_c) 00256 static_cast<Sequence&>(**i).set_leaf_sequence(++level); 00257 else if ((*i)->type() == dods_structure_c) 00258 static_cast<Structure&>(**i).set_leaf_sequence(level); 00259 } 00260 } 00261 00262 #if 0 00263 00267 void 00268 Structure::add_var(BaseType *bt, Part) 00269 { 00270 // Jose Garcia 00271 // Passing and invalid pointer to an object is a developer's error. 00272 if (!bt) 00273 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null."); 00274 00275 if (bt->is_dap4_only_type()) 00276 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure."); 00277 00278 // Jose Garcia 00279 // Now we add a copy of bt so the external user is able to destroy bt as 00280 // he/she wishes. The policy is: "If it is allocated outside, it is 00281 // deallocated outside, if it is allocated inside, it is deallocated 00282 // inside" 00283 BaseType *btp = bt->ptr_duplicate(); 00284 btp->set_parent(this); 00285 d_vars.push_back(btp); 00286 } 00287 00292 void 00293 Structure::add_var_nocopy(BaseType *bt, Part) 00294 { 00295 if (!bt) 00296 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null."); 00297 00298 if (bt->is_dap4_only_type()) 00299 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure."); 00300 00301 bt->set_parent(this); 00302 d_vars.push_back(bt); 00303 } 00304 00305 00309 void 00310 Structure::del_var(const string &n) 00311 { 00312 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00313 if ((*i)->name() == n) { 00314 BaseType *bt = *i ; 00315 d_vars.erase(i) ; 00316 delete bt ; bt = 0; 00317 return; 00318 } 00319 } 00320 } 00321 #endif 00322 #if 0 00323 00328 bool Structure::read() 00329 { 00330 if (!read_p()) { 00331 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00332 (*i)->read(); 00333 } 00334 set_read_p(true); 00335 } 00336 00337 return false; 00338 } 00339 #endif 00340 #if 0 00341 // TODO Recode to use width(bool) 00342 unsigned int 00343 Structure::width() 00344 { 00345 unsigned int sz = 0; 00346 00347 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00348 sz += (*i)->width(); 00349 } 00350 00351 return sz; 00352 } 00353 00361 unsigned int 00362 Structure::width(bool constrained) 00363 { 00364 unsigned int sz = 0; 00365 00366 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00367 if (constrained) { 00368 if ((*i)->send_p()) 00369 sz += (*i)->width(constrained); 00370 } 00371 else { 00372 sz += (*i)->width(constrained); 00373 } 00374 } 00375 00376 return sz; 00377 } 00378 #endif 00379 00380 #if 0 00381 void 00382 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds) 00383 { 00384 DBG(cerr << "Structure::intern_data: " << name() << endl); 00385 if (!read_p()) 00386 read(); // read() throws Error and InternalErr 00387 00388 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00389 if ((*i)->send_p()) { 00390 (*i)->intern_data(eval, dds); 00391 } 00392 } 00393 } 00394 00395 bool 00396 Structure::serialize(ConstraintEvaluator &eval, DDS &dds, 00397 Marshaller &m, bool ce_eval) 00398 { 00399 #if USE_LOCAL_TIMEOUT_SCHEME 00400 dds.timeout_on(); 00401 #endif 00402 if (!read_p()) 00403 read(); // read() throws Error and InternalErr 00404 00405 #if EVAL 00406 if (ce_eval && !eval.eval_selection(dds, dataset())) 00407 return true; 00408 #endif 00409 #if USE_LOCAL_TIMEOUT_SCHEME 00410 dds.timeout_off(); 00411 #endif 00412 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00413 if ((*i)->send_p()) { 00414 #ifdef CHECKSUMS 00415 XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m); 00416 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c) 00417 sm->reset_checksum(); 00418 00419 (*i)->serialize(eval, dds, m, false); 00420 00421 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c) 00422 sm->get_checksum(); 00423 #else 00424 (*i)->serialize(eval, dds, m, false); 00425 #endif 00426 } 00427 } 00428 00429 return true; 00430 } 00431 00432 bool 00433 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00434 { 00435 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00436 (*i)->deserialize(um, dds, reuse); 00437 } 00438 00439 return false; 00440 } 00441 #endif 00442 #if 0 00443 00452 unsigned int 00453 Structure::val2buf(void *, bool) 00454 { 00455 return sizeof(Structure); 00456 } 00457 00461 unsigned int 00462 Structure::buf2val(void **) 00463 { 00464 return sizeof(Structure); 00465 } 00466 #endif 00467 00468 #if 0 00469 BaseType * 00470 Structure::var(const string &name, bool exact_match, btp_stack *s) 00471 { 00472 string n = www2id(name); 00473 00474 if (exact_match) 00475 return m_exact_match(n, s); 00476 else 00477 return m_leaf_match(n, s); 00478 } 00479 00481 BaseType * 00482 Structure::var(const string &n, btp_stack &s) 00483 { 00484 string name = www2id(n); 00485 00486 BaseType *btp = m_exact_match(name, &s); 00487 if (btp) 00488 return btp; 00489 00490 return m_leaf_match(name, &s); 00491 } 00492 #endif 00493 #if 0 00494 // Private method to find a variable using the shorthand name. This 00495 // should be moved to Constructor. 00496 BaseType * 00497 Structure::m_leaf_match(const string &name, btp_stack *s) 00498 { 00499 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00500 if ((*i)->name() == name) { 00501 if (s) { 00502 DBG(cerr << "Pushing " << this->name() << endl); 00503 s->push(static_cast<BaseType *>(this)); 00504 } 00505 return *i; 00506 } 00507 if ((*i)->is_constructor_type()) { 00508 BaseType *btp = (*i)->var(name, false, s); 00509 if (btp) { 00510 if (s) { 00511 DBG(cerr << "Pushing " << this->name() << endl); 00512 s->push(static_cast<BaseType *>(this)); 00513 } 00514 return btp; 00515 } 00516 } 00517 } 00518 00519 return 0; 00520 } 00521 00522 // Breadth-first search for NAME. If NAME contains one or more dots (.) 00523 // TODO The btp_stack is not needed since there are 'back pointers' in 00524 // BaseType. 00525 BaseType * 00526 Structure::m_exact_match(const string &name, btp_stack *s) 00527 { 00528 // Look for name at the top level first. 00529 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00530 if ((*i)->name() == name) { 00531 if (s) 00532 s->push(static_cast<BaseType *>(this)); 00533 00534 return *i; 00535 } 00536 } 00537 00538 // If it was not found using the simple search, look for a dot and 00539 // search the hierarchy. 00540 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00541 if (dot_pos != string::npos) { 00542 string aggregate = name.substr(0, dot_pos); 00543 string field = name.substr(dot_pos + 1); 00544 00545 BaseType *agg_ptr = var(aggregate); 00546 if (agg_ptr) { 00547 if (s) 00548 s->push(static_cast<BaseType *>(this)); 00549 00550 return agg_ptr->var(field, true, s); // recurse 00551 } 00552 else 00553 return 0; // qualified names must be *fully* qualified 00554 } 00555 00556 return 0; 00557 } 00558 #endif 00559 #if 0 00560 void 00561 Structure::print_val(FILE *out, string space, bool print_decl_p) 00562 { 00563 ostringstream oss; 00564 print_val(oss, space, print_decl_p); 00565 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out); 00566 } 00567 00568 void 00569 Structure::print_val(ostream &out, string space, bool print_decl_p) 00570 { 00571 if (print_decl_p) { 00572 print_decl(out, space, false); 00573 out << " = " ; 00574 } 00575 00576 out << "{ " ; 00577 for (Vars_citer i = d_vars.begin(); i != d_vars.end(); 00578 i++, (void)(i != d_vars.end() && out << ", ")) { 00579 (*i)->print_val(out, "", false); 00580 } 00581 00582 out << " }" ; 00583 00584 if (print_decl_p) 00585 out << ";\n" ; 00586 } 00587 #endif 00588 00589 #if 0 00590 bool 00591 Structure::check_semantics(string &msg, bool all) 00592 { 00593 if (!BaseType::check_semantics(msg)) 00594 return false; 00595 00596 bool status = true; 00597 00598 if (!unique_names(d_vars, name(), type_name(), msg)) 00599 return false; 00600 00601 if (all) { 00602 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) { 00603 //assert(*i); 00604 if (!(*i)->check_semantics(msg, true)) { 00605 status = false; 00606 goto exit; 00607 } 00608 } 00609 } 00610 00611 exit: 00612 return status; 00613 } 00614 #endif 00615 00624 void 00625 Structure::dump(ostream &strm) const 00626 { 00627 strm << DapIndent::LMarg << "Structure::dump - (" 00628 << (void *)this << ")" << endl ; 00629 DapIndent::Indent() ; 00630 Constructor::dump(strm) ; 00631 DapIndent::UnIndent() ; 00632 } 00633 00634 } // namespace libdap 00635