libdap++
Updated for version 3.8.2
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "Byte.h" 00041 #include "Int16.h" 00042 #include "UInt16.h" 00043 #include "Int32.h" 00044 #include "UInt32.h" 00045 #include "Float32.h" 00046 #include "Float64.h" 00047 #include "Str.h" 00048 #include "Url.h" 00049 #include "Array.h" 00050 #include "Structure.h" 00051 #include "Sequence.h" 00052 #include "Grid.h" 00053 00054 #include "util.h" 00055 #include "debug.h" 00056 #include "InternalErr.h" 00057 #include "escaping.h" 00058 00059 using std::cerr; 00060 using std::endl; 00061 00062 namespace libdap { 00063 00064 void 00065 Structure::_duplicate(const Structure &s) 00066 { 00067 Structure &cs = const_cast<Structure &>(s); 00068 00069 DBG(cerr << "Copying structure: " << name() << endl); 00070 00071 for (Vars_iter i = cs._vars.begin(); i != cs._vars.end(); i++) { 00072 DBG(cerr << "Copying field: " << (*i)->name() << endl); 00073 // Jose Garcia 00074 // I think this assert here is part of a debugging 00075 // process since it is going along with a DBG call 00076 // I leave it here since it can be remove by defining NDEBUG. 00077 // assert(*i); 00078 BaseType *btp = (*i)->ptr_duplicate(); 00079 btp->set_parent(this); 00080 _vars.push_back(btp); 00081 } 00082 } 00083 00091 Structure::Structure(const string &n) : Constructor(n, dods_structure_c) 00092 {} 00093 00103 Structure::Structure(const string &n, const string &d) 00104 : Constructor(n, d, dods_structure_c) 00105 {} 00106 00108 Structure::Structure(const Structure &rhs) : Constructor(rhs) 00109 { 00110 _duplicate(rhs); 00111 } 00112 00113 Structure::~Structure() 00114 { 00115 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00116 BaseType *btp = *i ; 00117 delete btp ; btp = 0; 00118 } 00119 } 00120 00121 BaseType * 00122 Structure::ptr_duplicate() 00123 { 00124 return new Structure(*this); 00125 } 00126 00127 Structure & 00128 Structure::operator=(const Structure &rhs) 00129 { 00130 if (this == &rhs) 00131 return *this; 00132 00133 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00134 00135 _duplicate(rhs); 00136 00137 return *this; 00138 } 00139 00140 int 00141 Structure::element_count(bool leaves) 00142 { 00143 if (!leaves) 00144 return _vars.size(); 00145 else { 00146 int i = 0; 00147 for (Vars_iter j = _vars.begin(); j != _vars.end(); j++) { 00148 j += (*j)->element_count(leaves); 00149 } 00150 return i; 00151 } 00152 } 00153 00154 bool 00155 Structure::is_linear() 00156 { 00157 bool linear = true; 00158 for (Vars_iter i = _vars.begin(); linear && i != _vars.end(); i++) { 00159 if ((*i)->type() == dods_structure_c) 00160 linear = linear && dynamic_cast<Structure*>((*i))->is_linear(); 00161 else 00162 linear = linear && (*i)->is_simple_type(); 00163 } 00164 00165 return linear; 00166 } 00167 00168 void 00169 Structure::set_send_p(bool state) 00170 { 00171 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00172 (*i)->set_send_p(state); 00173 } 00174 00175 BaseType::set_send_p(state); 00176 } 00177 00178 void 00179 Structure::set_read_p(bool state) 00180 { 00181 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00182 (*i)->set_read_p(state); 00183 } 00184 00185 BaseType::set_read_p(state); 00186 } 00187 00193 void 00194 Structure::set_in_selection(bool state) 00195 { 00196 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00197 (*i)->set_in_selection(state); 00198 } 00199 00200 BaseType::set_in_selection(state); 00201 } 00202 00204 void 00205 Structure::set_leaf_sequence(int level) 00206 { 00207 for (Vars_iter i = var_begin(); i != var_end(); i++) { 00208 if ((*i)->type() == dods_sequence_c) 00209 dynamic_cast<Sequence&>(**i).set_leaf_sequence(++level); 00210 else if ((*i)->type() == dods_structure_c) 00211 dynamic_cast<Structure&>(**i).set_leaf_sequence(level); 00212 } 00213 } 00214 00219 void 00220 Structure::add_var(BaseType *bt, Part) 00221 { 00222 // Jose Garcia 00223 // Passing and invalid pointer to an object is a developer's error. 00224 if (!bt) 00225 throw InternalErr(__FILE__, __LINE__, 00226 "The BaseType parameter cannot be null."); 00227 00228 // Jose Garcia 00229 // Now we add a copy of bt so the external user is able to destroy bt as 00230 // he/she wishes. The policy is: "If it is allocated outside, it is 00231 // deallocated outside, if it is allocated inside, it is deallocated 00232 // inside" 00233 BaseType *btp = bt->ptr_duplicate(); 00234 btp->set_parent(this); 00235 _vars.push_back(btp); 00236 } 00237 00242 void 00243 Structure::add_var_nocopy(BaseType *bt, Part) 00244 { 00245 // Jose Garcia 00246 // Passing and invalid pointer to an object is a developer's error. 00247 if (!bt) 00248 throw InternalErr(__FILE__, __LINE__, 00249 "The BaseType parameter cannot be null."); 00250 00251 bt->set_parent(this); 00252 _vars.push_back(bt); 00253 } 00254 00255 00259 void 00260 Structure::del_var(const string &n) 00261 { 00262 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00263 if ((*i)->name() == n) { 00264 BaseType *bt = *i ; 00265 _vars.erase(i) ; 00266 delete bt ; bt = 0; 00267 return; 00268 } 00269 } 00270 } 00271 00277 bool 00278 Structure::read() 00279 { 00280 if( !read_p() ) 00281 { 00282 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00283 (*i)->read() ; 00284 } 00285 set_read_p(true) ; 00286 } 00287 00288 return false ; 00289 } 00290 00291 // TODO Recode to use width(bool) 00292 unsigned int 00293 Structure::width() 00294 { 00295 unsigned int sz = 0; 00296 00297 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00298 sz += (*i)->width(); 00299 } 00300 00301 return sz; 00302 } 00303 00311 unsigned int 00312 Structure::width(bool constrained) 00313 { 00314 unsigned int sz = 0; 00315 00316 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00317 if (constrained) { 00318 if ((*i)->send_p()) 00319 sz += (*i)->width(constrained); 00320 } 00321 else { 00322 sz += (*i)->width(constrained); 00323 } 00324 } 00325 00326 return sz; 00327 } 00328 00329 00330 void 00331 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds) 00332 { 00333 DBG(cerr << "Structure::intern_data: " << name() << endl); 00334 if (!read_p()) 00335 read(); // read() throws Error and InternalErr 00336 00337 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00338 if ((*i)->send_p()) { 00339 (*i)->intern_data(eval, dds); 00340 } 00341 } 00342 } 00343 00344 bool 00345 Structure::serialize(ConstraintEvaluator &eval, DDS &dds, 00346 Marshaller &m, bool ce_eval) 00347 { 00348 dds.timeout_on(); 00349 00350 if (!read_p()) 00351 read(); // read() throws Error and InternalErr 00352 00353 #if EVAL 00354 if (ce_eval && !eval.eval_selection(dds, dataset())) 00355 return true; 00356 #endif 00357 00358 dds.timeout_off(); 00359 00360 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00361 if ((*i)->send_p()) { 00362 (*i)->serialize(eval, dds, m, false); 00363 } 00364 } 00365 00366 return true; 00367 } 00368 00369 bool 00370 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00371 { 00372 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00373 (*i)->deserialize(um, dds, reuse); 00374 } 00375 00376 return false; 00377 } 00378 00388 unsigned int 00389 Structure::val2buf(void *, bool) 00390 { 00391 return sizeof(Structure); 00392 } 00393 00397 unsigned int 00398 Structure::buf2val(void **) 00399 { 00400 return sizeof(Structure); 00401 } 00402 00403 BaseType * 00404 Structure::var(const string &name, bool exact_match, btp_stack *s) 00405 { 00406 string n = www2id(name); 00407 00408 if (exact_match) 00409 return m_exact_match(n, s); 00410 else 00411 return m_leaf_match(n, s); 00412 } 00413 00415 BaseType * 00416 Structure::var(const string &n, btp_stack &s) 00417 { 00418 string name = www2id(n); 00419 00420 BaseType *btp = m_exact_match(name, &s); 00421 if (btp) 00422 return btp; 00423 00424 return m_leaf_match(name, &s); 00425 } 00426 00427 // Private method to find a variable using the shorthand name. This 00428 // should be moved to Constructor. 00429 BaseType * 00430 Structure::m_leaf_match(const string &name, btp_stack *s) 00431 { 00432 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00433 if ((*i)->name() == name) { 00434 if (s) { 00435 DBG(cerr << "Pushing " << this->name() << endl); 00436 s->push(static_cast<BaseType *>(this)); 00437 } 00438 return *i; 00439 } 00440 if ((*i)->is_constructor_type()) { 00441 BaseType *btp = (*i)->var(name, false, s); 00442 if (btp) { 00443 if (s) { 00444 DBG(cerr << "Pushing " << this->name() << endl); 00445 s->push(static_cast<BaseType *>(this)); 00446 } 00447 return btp; 00448 } 00449 } 00450 } 00451 00452 return 0; 00453 } 00454 00455 // Breadth-first search for NAME. If NAME contains one or more dots (.) 00456 BaseType * 00457 Structure::m_exact_match(const string &name, btp_stack *s) 00458 { 00459 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00460 DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i 00461 << endl); 00462 if ((*i)->name() == name) { 00463 DBG(cerr << "Found " << (*i)->name() << " in: " 00464 << *i << endl); 00465 if (s) { 00466 DBG(cerr << "Pushing " << this->name() << endl); 00467 s->push(static_cast<BaseType *>(this)); 00468 } 00469 return *i; 00470 } 00471 } 00472 00473 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00474 if (dot_pos != string::npos) { 00475 string aggregate = name.substr(0, dot_pos); 00476 string field = name.substr(dot_pos + 1); 00477 00478 BaseType *agg_ptr = var(aggregate); 00479 if (agg_ptr) { 00480 DBG(cerr << "Descending into " << agg_ptr->name() << endl); 00481 if (s) { 00482 DBG(cerr << "Pushing " << this->name() << endl); 00483 s->push(static_cast<BaseType *>(this)); 00484 } 00485 return agg_ptr->var(field, true, s); // recurse 00486 } 00487 else 00488 return 0; // qualified names must be *fully* qualified 00489 } 00490 00491 return 0; 00492 } 00493 00494 #if FILE_METHODS 00495 void 00496 Structure::print_val(FILE *out, string space, bool print_decl_p) 00497 { 00498 if (print_decl_p) { 00499 print_decl(out, space, false); 00500 fprintf(out, " = ") ; 00501 } 00502 00503 fprintf(out, "{ ") ; 00504 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00505 i++, (void)(i != _vars.end() && fprintf(out, ", "))) { 00506 (*i)->print_val(out, "", false); 00507 } 00508 00509 fprintf(out, " }") ; 00510 00511 if (print_decl_p) 00512 fprintf(out, ";\n") ; 00513 } 00514 #endif 00515 00516 void 00517 Structure::print_val(ostream &out, string space, bool print_decl_p) 00518 { 00519 if (print_decl_p) { 00520 print_decl(out, space, false); 00521 out << " = " ; 00522 } 00523 00524 out << "{ " ; 00525 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00526 i++, (void)(i != _vars.end() && out << ", ")) { 00527 (*i)->print_val(out, "", false); 00528 } 00529 00530 out << " }" ; 00531 00532 if (print_decl_p) 00533 out << ";\n" ; 00534 } 00535 00536 bool 00537 Structure::check_semantics(string &msg, bool all) 00538 { 00539 if (!BaseType::check_semantics(msg)) 00540 return false; 00541 00542 bool status = true; 00543 00544 if (!unique_names(_vars, name(), type_name(), msg)) 00545 return false; 00546 00547 if (all) { 00548 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00549 //assert(*i); 00550 if (!(*i)->check_semantics(msg, true)) { 00551 status = false; 00552 goto exit; 00553 } 00554 } 00555 } 00556 00557 exit: 00558 return status; 00559 } 00560 00569 void 00570 Structure::dump(ostream &strm) const 00571 { 00572 strm << DapIndent::LMarg << "Structure::dump - (" 00573 << (void *)this << ")" << endl ; 00574 DapIndent::Indent() ; 00575 Constructor::dump(strm) ; 00576 DapIndent::UnIndent() ; 00577 } 00578 00579 } // namespace libdap 00580