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 00241 void 00242 Structure::del_var(const string &n) 00243 { 00244 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00245 if ((*i)->name() == n) { 00246 BaseType *bt = *i ; 00247 _vars.erase(i) ; 00248 delete bt ; bt = 0; 00249 return; 00250 } 00251 } 00252 } 00253 00259 bool 00260 Structure::read() 00261 { 00262 if( !read_p() ) 00263 { 00264 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00265 (*i)->read() ; 00266 } 00267 set_read_p(true) ; 00268 } 00269 00270 return false ; 00271 } 00272 00273 unsigned int 00274 Structure::width() 00275 { 00276 unsigned int sz = 0; 00277 00278 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00279 sz += (*i)->width(); 00280 } 00281 00282 return sz; 00283 } 00284 00285 void 00286 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds) 00287 { 00288 DBG(cerr << "Structure::intern_data: " << name() << endl); 00289 if (!read_p()) 00290 read(); // read() throws Error and InternalErr 00291 00292 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00293 if ((*i)->send_p()) { 00294 (*i)->intern_data(eval, dds); 00295 } 00296 } 00297 } 00298 00299 bool 00300 Structure::serialize(ConstraintEvaluator &eval, DDS &dds, 00301 Marshaller &m, bool ce_eval) 00302 { 00303 dds.timeout_on(); 00304 00305 if (!read_p()) 00306 read(); // read() throws Error and InternalErr 00307 00308 #if EVAL 00309 if (ce_eval && !eval.eval_selection(dds, dataset())) 00310 return true; 00311 #endif 00312 00313 dds.timeout_off(); 00314 00315 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00316 if ((*i)->send_p()) { 00317 (*i)->serialize(eval, dds, m, false); 00318 } 00319 } 00320 00321 return true; 00322 } 00323 00324 bool 00325 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse) 00326 { 00327 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00328 (*i)->deserialize(um, dds, reuse); 00329 } 00330 00331 return false; 00332 } 00333 00343 unsigned int 00344 Structure::val2buf(void *, bool) 00345 { 00346 return sizeof(Structure); 00347 } 00348 00352 unsigned int 00353 Structure::buf2val(void **) 00354 { 00355 return sizeof(Structure); 00356 } 00357 00358 BaseType * 00359 Structure::var(const string &name, bool exact_match, btp_stack *s) 00360 { 00361 string n = www2id(name); 00362 00363 if (exact_match) 00364 return m_exact_match(n, s); 00365 else 00366 return m_leaf_match(n, s); 00367 } 00368 00370 BaseType * 00371 Structure::var(const string &n, btp_stack &s) 00372 { 00373 string name = www2id(n); 00374 00375 BaseType *btp = m_exact_match(name, &s); 00376 if (btp) 00377 return btp; 00378 00379 return m_leaf_match(name, &s); 00380 } 00381 00382 // Private method to find a variable using the shorthand name. This 00383 // should be moved to Constructor. 00384 BaseType * 00385 Structure::m_leaf_match(const string &name, btp_stack *s) 00386 { 00387 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00388 if ((*i)->name() == name) { 00389 if (s) { 00390 DBG(cerr << "Pushing " << this->name() << endl); 00391 s->push(static_cast<BaseType *>(this)); 00392 } 00393 return *i; 00394 } 00395 if ((*i)->is_constructor_type()) { 00396 BaseType *btp = (*i)->var(name, false, s); 00397 if (btp) { 00398 if (s) { 00399 DBG(cerr << "Pushing " << this->name() << endl); 00400 s->push(static_cast<BaseType *>(this)); 00401 } 00402 return btp; 00403 } 00404 } 00405 } 00406 00407 return 0; 00408 } 00409 00410 // Breadth-first search for NAME. If NAME contains one or more dots (.) 00411 BaseType * 00412 Structure::m_exact_match(const string &name, btp_stack *s) 00413 { 00414 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00415 DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i 00416 << endl); 00417 if ((*i)->name() == name) { 00418 DBG(cerr << "Found " << (*i)->name() << " in: " 00419 << *i << endl); 00420 if (s) { 00421 DBG(cerr << "Pushing " << this->name() << endl); 00422 s->push(static_cast<BaseType *>(this)); 00423 } 00424 return *i; 00425 } 00426 } 00427 00428 string::size_type dot_pos = name.find("."); // zero-based index of `.' 00429 if (dot_pos != string::npos) { 00430 string aggregate = name.substr(0, dot_pos); 00431 string field = name.substr(dot_pos + 1); 00432 00433 BaseType *agg_ptr = var(aggregate); 00434 if (agg_ptr) { 00435 DBG(cerr << "Descending into " << agg_ptr->name() << endl); 00436 if (s) { 00437 DBG(cerr << "Pushing " << this->name() << endl); 00438 s->push(static_cast<BaseType *>(this)); 00439 } 00440 return agg_ptr->var(field, true, s); // recurse 00441 } 00442 else 00443 return 0; // qualified names must be *fully* qualified 00444 } 00445 00446 return 0; 00447 } 00448 00449 #if FILE_METHODS 00450 void 00451 Structure::print_val(FILE *out, string space, bool print_decl_p) 00452 { 00453 if (print_decl_p) { 00454 print_decl(out, space, false); 00455 fprintf(out, " = ") ; 00456 } 00457 00458 fprintf(out, "{ ") ; 00459 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00460 i++, (void)(i != _vars.end() && fprintf(out, ", "))) { 00461 (*i)->print_val(out, "", false); 00462 } 00463 00464 fprintf(out, " }") ; 00465 00466 if (print_decl_p) 00467 fprintf(out, ";\n") ; 00468 } 00469 #endif 00470 00471 void 00472 Structure::print_val(ostream &out, string space, bool print_decl_p) 00473 { 00474 if (print_decl_p) { 00475 print_decl(out, space, false); 00476 out << " = " ; 00477 } 00478 00479 out << "{ " ; 00480 for (Vars_citer i = _vars.begin(); i != _vars.end(); 00481 i++, (void)(i != _vars.end() && out << ", ")) { 00482 (*i)->print_val(out, "", false); 00483 } 00484 00485 out << " }" ; 00486 00487 if (print_decl_p) 00488 out << ";\n" ; 00489 } 00490 00491 bool 00492 Structure::check_semantics(string &msg, bool all) 00493 { 00494 if (!BaseType::check_semantics(msg)) 00495 return false; 00496 00497 bool status = true; 00498 00499 if (!unique_names(_vars, name(), type_name(), msg)) 00500 return false; 00501 00502 if (all) { 00503 for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) { 00504 //assert(*i); 00505 if (!(*i)->check_semantics(msg, true)) { 00506 status = false; 00507 goto exit; 00508 } 00509 } 00510 } 00511 00512 exit: 00513 return status; 00514 } 00515 00524 void 00525 Structure::dump(ostream &strm) const 00526 { 00527 strm << DapIndent::LMarg << "Structure::dump - (" 00528 << (void *)this << ")" << endl ; 00529 DapIndent::Indent() ; 00530 Constructor::dump(strm) ; 00531 DapIndent::UnIndent() ; 00532 } 00533 00534 } // namespace libdap 00535