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 
00242 void
00243 Structure::add_var_nocopy(BaseType *bt, Part)
00244 {
00245     // Jose Garcia
00246     // Passing and invalid pointer to an object is a developer's error.
00247     if (!bt)
00248         throw InternalErr(__FILE__, __LINE__,
00249                           "The BaseType parameter cannot be null.");
00250 
00251     bt->set_parent(this);
00252     _vars.push_back(bt);
00253 }
00254 
00255 
00259 void
00260 Structure::del_var(const string &n)
00261 {
00262     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00263         if ((*i)->name() == n) {
00264             BaseType *bt = *i ;
00265             _vars.erase(i) ;
00266             delete bt ; bt = 0;
00267             return;
00268         }
00269     }
00270 }
00271 
00277 bool
00278 Structure::read()
00279 {
00280     if( !read_p() )
00281     {
00282         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00283             (*i)->read() ;
00284         }
00285         set_read_p(true) ;
00286     }
00287 
00288     return false ;
00289 }
00290 
00291 // TODO Recode to use width(bool)
00292 unsigned int
00293 Structure::width()
00294 {
00295     unsigned int sz = 0;
00296 
00297     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00298         sz += (*i)->width();
00299     }
00300 
00301     return sz;
00302 }
00303 
00311 unsigned int
00312 Structure::width(bool constrained)
00313 {
00314     unsigned int sz = 0;
00315 
00316     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00317         if (constrained) {
00318                 if ((*i)->send_p())
00319                         sz += (*i)->width(constrained);
00320         }
00321         else {
00322                 sz += (*i)->width(constrained);
00323         }
00324     }
00325 
00326     return sz;
00327 }
00328 
00329 
00330 void
00331 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
00332 {
00333     DBG(cerr << "Structure::intern_data: " << name() << endl);
00334     if (!read_p())
00335         read();          // read() throws Error and InternalErr
00336 
00337     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00338         if ((*i)->send_p()) {
00339             (*i)->intern_data(eval, dds);
00340         }
00341     }
00342 }
00343 
00344 bool
00345 Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
00346                      Marshaller &m, bool ce_eval)
00347 {
00348     dds.timeout_on();
00349 
00350     if (!read_p())
00351         read();  // read() throws Error and InternalErr
00352 
00353 #if EVAL
00354     if (ce_eval && !eval.eval_selection(dds, dataset()))
00355         return true;
00356 #endif
00357 
00358     dds.timeout_off();
00359 
00360     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00361         if ((*i)->send_p()) {
00362             (*i)->serialize(eval, dds, m, false);
00363         }
00364     }
00365 
00366     return true;
00367 }
00368 
00369 bool
00370 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
00371 {
00372     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00373         (*i)->deserialize(um, dds, reuse);
00374     }
00375 
00376     return false;
00377 }
00378 
00388 unsigned int
00389 Structure::val2buf(void *, bool)
00390 {
00391     return sizeof(Structure);
00392 }
00393 
00397 unsigned int
00398 Structure::buf2val(void **)
00399 {
00400     return sizeof(Structure);
00401 }
00402 
00403 BaseType *
00404 Structure::var(const string &name, bool exact_match, btp_stack *s)
00405 {
00406     string n = www2id(name);
00407 
00408     if (exact_match)
00409         return m_exact_match(n, s);
00410     else
00411         return m_leaf_match(n, s);
00412 }
00413 
00415 BaseType *
00416 Structure::var(const string &n, btp_stack &s)
00417 {
00418     string name = www2id(n);
00419 
00420     BaseType *btp = m_exact_match(name, &s);
00421     if (btp)
00422         return btp;
00423 
00424     return m_leaf_match(name, &s);
00425 }
00426 
00427 // Private method to find a variable using the shorthand name. This
00428 // should be moved to Constructor.
00429 BaseType *
00430 Structure::m_leaf_match(const string &name, btp_stack *s)
00431 {
00432     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00433         if ((*i)->name() == name) {
00434             if (s) {
00435                 DBG(cerr << "Pushing " << this->name() << endl);
00436                 s->push(static_cast<BaseType *>(this));
00437             }
00438             return *i;
00439         }
00440         if ((*i)->is_constructor_type()) {
00441             BaseType *btp = (*i)->var(name, false, s);
00442             if (btp) {
00443                 if (s) {
00444                     DBG(cerr << "Pushing " << this->name() << endl);
00445                     s->push(static_cast<BaseType *>(this));
00446                 }
00447                 return btp;
00448             }
00449         }
00450     }
00451 
00452     return 0;
00453 }
00454 
00455 // Breadth-first search for NAME. If NAME contains one or more dots (.)
00456 BaseType *
00457 Structure::m_exact_match(const string &name, btp_stack *s)
00458 {
00459     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00460         DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i
00461             << endl);
00462         if ((*i)->name() == name) {
00463             DBG(cerr << "Found " << (*i)->name() << " in: "
00464                 << *i << endl);
00465             if (s) {
00466                 DBG(cerr << "Pushing " << this->name() << endl);
00467                 s->push(static_cast<BaseType *>(this));
00468             }
00469             return *i;
00470         }
00471     }
00472 
00473     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00474     if (dot_pos != string::npos) {
00475         string aggregate = name.substr(0, dot_pos);
00476         string field = name.substr(dot_pos + 1);
00477 
00478         BaseType *agg_ptr = var(aggregate);
00479         if (agg_ptr) {
00480             DBG(cerr << "Descending into " << agg_ptr->name() << endl);
00481             if (s) {
00482                 DBG(cerr << "Pushing " << this->name() << endl);
00483                 s->push(static_cast<BaseType *>(this));
00484             }
00485             return agg_ptr->var(field, true, s); // recurse
00486         }
00487         else
00488             return 0;  // qualified names must be *fully* qualified
00489     }
00490 
00491     return 0;
00492 }
00493 
00494 #if FILE_METHODS
00495 void
00496 Structure::print_val(FILE *out, string space, bool print_decl_p)
00497 {
00498     if (print_decl_p) {
00499         print_decl(out, space, false);
00500         fprintf(out, " = ") ;
00501     }
00502 
00503     fprintf(out, "{ ") ;
00504     for (Vars_citer i = _vars.begin(); i != _vars.end();
00505          i++, (void)(i != _vars.end() && fprintf(out, ", "))) {
00506         (*i)->print_val(out, "", false);
00507     }
00508 
00509     fprintf(out, " }") ;
00510 
00511     if (print_decl_p)
00512         fprintf(out, ";\n") ;
00513 }
00514 #endif
00515 
00516 void
00517 Structure::print_val(ostream &out, string space, bool print_decl_p)
00518 {
00519     if (print_decl_p) {
00520         print_decl(out, space, false);
00521         out << " = " ;
00522     }
00523 
00524     out << "{ " ;
00525     for (Vars_citer i = _vars.begin(); i != _vars.end();
00526          i++, (void)(i != _vars.end() && out << ", ")) {
00527         (*i)->print_val(out, "", false);
00528     }
00529 
00530     out << " }" ;
00531 
00532     if (print_decl_p)
00533         out << ";\n" ;
00534 }
00535 
00536 bool
00537 Structure::check_semantics(string &msg, bool all)
00538 {
00539     if (!BaseType::check_semantics(msg))
00540         return false;
00541 
00542     bool status = true;
00543 
00544     if (!unique_names(_vars, name(), type_name(), msg))
00545         return false;
00546 
00547     if (all) {
00548         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00549             //assert(*i);
00550             if (!(*i)->check_semantics(msg, true)) {
00551                 status = false;
00552                 goto exit;
00553             }
00554         }
00555     }
00556 
00557 exit:
00558     return status;
00559 }
00560 
00569 void
00570 Structure::dump(ostream &strm) const
00571 {
00572     strm << DapIndent::LMarg << "Structure::dump - ("
00573     << (void *)this << ")" << endl ;
00574     DapIndent::Indent() ;
00575     Constructor::dump(strm) ;
00576     DapIndent::UnIndent() ;
00577 }
00578 
00579 } // namespace libdap
00580