libdap++ Updated for version 3.8.2

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 "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