Structure.cc

Go to the documentation of this file.
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 

Generated on Mon May 18 10:25:03 2009 for libdap++ by  doxygen 1.4.7