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 "Structure.h" 00041 #include "util.h" 00042 #include "debug.h" 00043 #include "InternalErr.h" 00044 #include "escaping.h" 00045 00046 using std::cerr; 00047 using std::endl; 00048 00049 namespace libdap { 00050 00051 void 00052 Structure::_duplicate(const Structure &s) 00053 { 00054 Structure &cs = const_cast<Structure &>(s); 00055 00056 DBG(cerr << "Copying structure: " << name() << endl); 00057 00058 for (Vars_iter i = cs._vars.begin(); i != cs._vars.end(); i++) { 00059 DBG(cerr << "Copying field: " << (*i)->name() << endl); 00060 // Jose Garcia 00061 // I think this assert here is part of a debugging 00062 // process since it is going along with a DBG call 00063 // I leave it here since it can be remove by defining NDEBUG. 00064 // assert(*i); 00065 BaseType *btp = (*i)->ptr_duplicate(); 00066 btp->set_parent(this); 00067 _vars.push_back(btp); 00068 } 00069 } 00070 00078 Structure::Structure(const string &n) : Constructor(n, dods_structure_c) 00079 {} 00080 00090 Structure::Structure(const string &n, const string &d) 00091 : Constructor(n, d, dods_structure_c) 00092 {} 00093 00095 Structure::Structure(const Structure &rhs) : Constructor(rhs) 00096 { 00097 _duplicate(rhs); 00098 } 00099 00100 Structure::~Structure() 00101 { 00102 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00103 BaseType *btp = *i ; 00104 delete btp ; btp = 0; 00105 } 00106 } 00107 00108 BaseType * 00109 Structure::ptr_duplicate() 00110 { 00111 return new Structure(*this); 00112 } 00113 00114 Structure & 00115 Structure::operator=(const Structure &rhs) 00116 { 00117 if (this == &rhs) 00118 return *this; 00119 00120 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor= 00121 00122 _duplicate(rhs); 00123 00124 return *this; 00125 } 00126 00127 int 00128 Structure::element_count(bool leaves) 00129 { 00130 if (!leaves) 00131 return _vars.size(); 00132 else { 00133 int i = 0; 00134 for (Vars_iter j = _vars.begin(); j != _vars.end(); j++) { 00135 j += (*j)->element_count(leaves); 00136 } 00137 return i; 00138 } 00139 } 00140 00141 bool 00142 Structure::is_linear() 00143 { 00144 bool linear = true; 00145 for (Vars_iter i = _vars.begin(); linear && i != _vars.end(); i++) { 00146 if ((*i)->type() == dods_structure_c) 00147 linear = linear && dynamic_cast<Structure*>((*i))->is_linear(); 00148 else 00149 linear = linear && (*i)->is_simple_type(); 00150 } 00151 00152 return linear; 00153 } 00154 00155 void 00156 Structure::set_send_p(bool state) 00157 { 00158 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00159 (*i)->set_send_p(state); 00160 } 00161 00162 BaseType::set_send_p(state); 00163 } 00164 00165 void 00166 Structure::set_read_p(bool state) 00167 { 00168 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00169 (*i)->set_read_p(state); 00170 } 00171 00172 BaseType::set_read_p(state); 00173 } 00174 00180 void 00181 Structure::set_in_selection(bool state) 00182 { 00183 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00184 (*i)->set_in_selection(state); 00185 } 00186 00187 BaseType::set_in_selection(state); 00188 } 00189 00191 void 00192 Structure::set_leaf_sequence(int level) 00193 { 00194 for (Vars_iter i = var_begin(); i != var_end(); i++) { 00195 if ((*i)->type() == dods_sequence_c) 00196 dynamic_cast<Sequence&>(**i).set_leaf_sequence(++level); 00197 else if ((*i)->type() == dods_structure_c) 00198 dynamic_cast<Structure&>(**i).set_leaf_sequence(level); 00199 } 00200 } 00201 00206 void 00207 Structure::add_var(BaseType *bt, Part) 00208 { 00209 // Jose Garcia 00210 // Passing and invalid pointer to an object is a developer's error. 00211 if (!bt) 00212 throw InternalErr(__FILE__, __LINE__, 00213 "The BaseType parameter cannot be null."); 00214 00215 // Jose Garcia 00216 // Now we add a copy of bt so the external user is able to destroy bt as 00217 // he/she wishes. The policy is: "If it is allocated outside, it is 00218 // deallocated outside, if it is allocated inside, it is deallocated 00219 // inside" 00220 BaseType *btp = bt->ptr_duplicate(); 00221 btp->set_parent(this); 00222 _vars.push_back(btp); 00223 } 00224 00228 void 00229 Structure::del_var(const string &n) 00230 { 00231 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00232 if ((*i)->name() == n) { 00233 BaseType *bt = *i ; 00234 _vars.erase(i) ; 00235 delete bt ; bt = 0; 00236 return; 00237 } 00238 } 00239 } 00240 00246 bool 00247 Structure::read() 00248 { 00249 if( !read_p() ) 00250 { 00251 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00252 (*i)->read() ; 00253 } 00254 set_read_p(true) ; 00255 } 00256 00257 return false ; 00258 } 00259 00260 unsigned int 00261 Structure::width() 00262 { 00263 unsigned int sz = 0; 00264 00265 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00266 sz += (*i)->width(); 00267 } 00268 00269 return sz; 00270 } 00271 00272 void 00273 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds) 00274 { 00275 DBG(cerr << "Structure::intern_data: " << name() << endl); 00276 if (!read_p()) 00277 read(); // read() throws Error and InternalErr 00278 00279 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00280 if ((*i)->send_p()) { 00281 (*i)->intern_data(eval, dds); 00282 } 00283 } 00284 } 00285 00286 bool 00287 Structure::serialize(ConstraintEvaluator &eval, DDS &dds, 00288 Marshaller &m, bool ce_eval) 00289 { 00290 dds.timeout_on(); 00291 00292 if (!read_p()) 00293 read(); // read() throws Error and InternalErr 00294 00295 #if EVAL 00296 if (ce_eval && !eval.eval_selection(dds, dataset())) 00297 return true; 00298 #endif 00299 00300 dds.timeout_off(); 00301 00302 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00303 if ((*i)->send_p()) { 00304 (*i)->serialize(eval, dds, m, false); 00305 } 00306 } 00307 00308 return true; 00309 } 00310 00311 bool 00312 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00313 { 00314 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00315 (*i)->deserialize(um, dds, reuse); 00316 } 00317 00318 return false; 00319 } 00320 00330 unsigned int 00331 Structure::val2buf(void *, bool) 00332 { 00333 return sizeof(Structure); 00334 } 00335 00339 unsigned int 00340 Structure::buf2val(void **) 00341 { 00342 return sizeof(Structure); 00343 } 00344 00345 BaseType * 00346 Structure::var(const string &name, bool exact_match, btp_stack *s) 00347 { 00348 string n = www2id(name); 00349 00350 if (exact_match) 00351 return m_exact_match(n, s); 00352 else 00353 return m_leaf_match(n, s); 00354 } 00355 00357 BaseType * 00358 Structure::var(const string &n, btp_stack &s) 00359 { 00360 string name = www2id(n); 00361 00362 BaseType *btp = m_exact_match(name, &s); 00363 if (btp) 00364 return btp; 00365 00366 return m_leaf_match(name, &s); 00367 } 00368 00369 // Private method to find a variable using the shorthand name. This 00370 // should be moved to Constructor. 00371 BaseType * 00372 Structure::m_leaf_match(const string &name, btp_stack *s) 00373 { 00374 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00375 if ((*i)->name() == name) { 00376 if (s) { 00377 DBG(cerr << "Pushing " << this->name() << endl); 00378 s->push(static_cast<BaseType *>(this)); 00379 } 00380 return *i; 00381 } 00382 if ((*i)->is_constructor_type()) { 00383 BaseType *btp = (*i)->var(name, false, s); 00384 if (btp) { 00385 if (s) { 00386 DBG(cerr << "Pushing " << this->name() << endl); 00387 s->push(static_cast<BaseType *>(this)); 00388 } 00389 return btp; 00390 } 00391 } 00392 } 00393 00394 return 0; 00395 } 00396 00397 // Breadth-first search for NAME. If NAME contains one or more dots (.) 00398 BaseType * 00399 Structure::m_exact_match(const string &name, btp_stack *s) 00400 { 00401 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00402 DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i 00403 << endl); 00404 if ((*i)->name() == name) { 00405 DBG(cerr << "Found " << (*i)->name() << " in: " 00406 << *i << endl); 00407 if (s) { 00408 DBG(cerr << "Pushing " << this->name() << endl); 00409 s->push(static_cast<BaseType *>(this)); 00410 } 00411 return *i; 00412 } 00413 } 00414 00415 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00416 if (dot_pos != string::npos) { 00417 string aggregate = name.substr(0, dot_pos); 00418 string field = name.substr(dot_pos + 1); 00419 00420 BaseType *agg_ptr = var(aggregate); 00421 if (agg_ptr) { 00422 DBG(cerr << "Descending into " << agg_ptr->name() << endl); 00423 if (s) { 00424 DBG(cerr << "Pushing " << this->name() << endl); 00425 s->push(static_cast<BaseType *>(this)); 00426 } 00427 return agg_ptr->var(field, true, s); // recurse 00428 } 00429 else 00430 return 0; // qualified names must be *fully* qualified 00431 } 00432 00433 return 0; 00434 } 00435 //#if FILE_METHODS 00436 void 00437 Structure::print_val(FILE *out, string space, bool print_decl_p) 00438 { 00439 if (print_decl_p) { 00440 print_decl(out, space, false); 00441 fprintf(out, " = ") ; 00442 } 00443 00444 fprintf(out, "{ ") ; 00445 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00446 i++, (void)(i != _vars.end() && fprintf(out, ", "))) { 00447 (*i)->print_val(out, "", false); 00448 } 00449 00450 fprintf(out, " }") ; 00451 00452 if (print_decl_p) 00453 fprintf(out, ";\n") ; 00454 } 00455 //#endif 00456 void 00457 Structure::print_val(ostream &out, string space, bool print_decl_p) 00458 { 00459 if (print_decl_p) { 00460 print_decl(out, space, false); 00461 out << " = " ; 00462 } 00463 00464 out << "{ " ; 00465 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00466 i++, (void)(i != _vars.end() && out << ", ")) { 00467 (*i)->print_val(out, "", false); 00468 } 00469 00470 out << " }" ; 00471 00472 if (print_decl_p) 00473 out << ";\n" ; 00474 } 00475 00476 bool 00477 Structure::check_semantics(string &msg, bool all) 00478 { 00479 if (!BaseType::check_semantics(msg)) 00480 return false; 00481 00482 bool status = true; 00483 00484 if (!unique_names(_vars, name(), type_name(), msg)) 00485 return false; 00486 00487 if (all) { 00488 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00489 //assert(*i); 00490 if (!(*i)->check_semantics(msg, true)) { 00491 status = false; 00492 goto exit; 00493 } 00494 } 00495 } 00496 00497 exit: 00498 return status; 00499 } 00500 00509 void 00510 Structure::dump(ostream &strm) const 00511 { 00512 strm << DapIndent::LMarg << "Structure::dump - (" 00513 << (void *)this << ")" << endl ; 00514 DapIndent::Indent() ; 00515 Constructor::dump(strm) ; 00516 DapIndent::UnIndent() ; 00517 } 00518 00519 } // namespace libdap 00520