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

Generated on Tue Mar 4 18:01:55 2008 for libdap++ by  doxygen 1.5.1