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 <stdlib.h>
00040 
00041 #include "Structure.h"
00042 #include "util.h"
00043 #include "debug.h"
00044 #include "InternalErr.h"
00045 #include "escaping.h"
00046 
00047 using std::cerr;
00048 using std::endl;
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 
00211 unsigned int
00212 Structure::width()
00213 {
00214     unsigned int sz = 0;
00215 
00216     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00217         sz += (*i)->width();
00218     }
00219 
00220     return sz;
00221 }
00222 
00223 void
00224 Structure::transfer_data(const string & dataset,
00225                          ConstraintEvaluator & eval, DDS & dds)
00226 {
00227     if (!read_p())
00228         read(dataset);          // read() throws Error and InternalErr
00229 
00230     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00231         if ((*i)->send_p()) {
00232             switch ((*i)->type()) {
00233             case dods_sequence_c:
00234                 dynamic_cast <Sequence & >(**i).transfer_data(dataset,
00235                         eval, dds);
00236                 break;
00237 
00238             case dods_structure_c:
00239                 dynamic_cast <Structure & >(**i).transfer_data(dataset,
00240                         eval, dds);
00241                 break;
00242 
00243             default:
00244                 (*i)->read(dataset);
00245                 break;
00246             }
00247         }
00248     }
00249 }
00250 
00251 bool
00252 Structure::serialize(const string &dataset, ConstraintEvaluator &eval, DDS &dds,
00253                      XDR *sink, bool ce_eval)
00254 {
00255     dds.timeout_on();
00256 
00257     if (!read_p())
00258         read(dataset);  // read() throws Error and InternalErr
00259 
00260 #if EVAL
00261     if (ce_eval && !eval.eval_selection(dds, dataset))
00262         return true;
00263 #endif
00264     dds.timeout_off();
00265 
00266     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00267         if ((*i)->send_p()) {
00268             (*i)->serialize(dataset, eval, dds, sink, false);
00269         }
00270     }
00271 
00272     return true;
00273 }
00274 
00275 bool
00276 Structure::deserialize(XDR *source, DDS *dds, bool reuse)
00277 {
00278     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00279         (*i)->deserialize(source, dds, reuse);
00280     }
00281 
00282     return false;
00283 }
00284 
00294 unsigned int
00295 Structure::val2buf(void *, bool)
00296 {
00297     return sizeof(Structure);
00298 }
00299 
00303 unsigned int
00304 Structure::buf2val(void **)
00305 {
00306     return sizeof(Structure);
00307 }
00308 
00309 BaseType *
00310 Structure::var(const string &name, bool exact_match, btp_stack *s)
00311 {
00312     string n = www2id(name);
00313 
00314     if (exact_match)
00315         return m_exact_match(n, s);
00316     else
00317         return m_leaf_match(n, s);
00318 }
00319 
00321 BaseType *
00322 Structure::var(const string &n, btp_stack &s)
00323 {
00324     string name = www2id(n);
00325 
00326     BaseType *btp = m_exact_match(name, &s);
00327     if (btp)
00328         return btp;
00329 
00330     return m_leaf_match(name, &s);
00331 }
00332 
00333 // Private method to find a variable using the shorthand name. This
00334 // should be moved to Constructor.
00335 BaseType *
00336 Structure::m_leaf_match(const string &name, btp_stack *s)
00337 {
00338     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00339         if ((*i)->name() == name) {
00340             if (s) {
00341                 DBG(cerr << "Pushing " << this->name() << endl);
00342                 s->push(static_cast<BaseType *>(this));
00343             }
00344             return *i;
00345         }
00346         if ((*i)->is_constructor_type()) {
00347             BaseType *btp = (*i)->var(name, false, s);
00348             if (btp) {
00349                 if (s) {
00350                     DBG(cerr << "Pushing " << this->name() << endl);
00351                     s->push(static_cast<BaseType *>(this));
00352                 }
00353                 return btp;
00354             }
00355         }
00356     }
00357 
00358     return 0;
00359 }
00360 
00361 // Breadth-first search for NAME. If NAME contains one or more dots (.) 
00362 BaseType *
00363 Structure::m_exact_match(const string &name, btp_stack *s)
00364 {
00365     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00366         DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i
00367             << endl);
00368         if ((*i)->name() == name) {
00369             DBG(cerr << "Found " << (*i)->name() << " in: "
00370                 << *i << endl);
00371             if (s) {
00372                 DBG(cerr << "Pushing " << this->name() << endl);
00373                 s->push(static_cast<BaseType *>(this));
00374             }
00375             return *i;
00376         }
00377     }
00378 
00379     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00380     if (dot_pos != string::npos) {
00381         string aggregate = name.substr(0, dot_pos);
00382         string field = name.substr(dot_pos + 1);
00383 
00384         BaseType *agg_ptr = var(aggregate);
00385         if (agg_ptr) {
00386             DBG(cerr << "Descending into " << agg_ptr->name() << endl);
00387             if (s) {
00388                 DBG(cerr << "Pushing " << this->name() << endl);
00389                 s->push(static_cast<BaseType *>(this));
00390             }
00391             return agg_ptr->var(field, true, s); // recurse
00392         }
00393         else
00394             return 0;  // qualified names must be *fully* qualified
00395     }
00396 
00397     return 0;
00398 }
00399 
00400 void
00401 Structure::print_val(FILE *out, string space, bool print_decl_p)
00402 {
00403     if (print_decl_p) {
00404         print_decl(out, space, false);
00405         fprintf(out, " = ") ;
00406     }
00407 
00408     fprintf(out, "{ ") ;
00409     for (Vars_citer i = _vars.begin(); i != _vars.end();
00410          i++, (void)(i != _vars.end() && fprintf(out, ", "))) {
00411         (*i)->print_val(out, "", false);
00412     }
00413 
00414     fprintf(out, " }") ;
00415 
00416     if (print_decl_p)
00417         fprintf(out, ";\n") ;
00418 }
00419 
00420 void
00421 Structure::print_all_vals(FILE *out, XDR *, DDS *, string space, bool print_decl_p)
00422 {
00423     print_val(out, space, print_decl_p);
00424 }
00425 
00426 bool
00427 Structure::check_semantics(string &msg, bool all)
00428 {
00429     if (!BaseType::check_semantics(msg))
00430         return false;
00431 
00432     bool status = true;
00433 
00434     if (!unique_names(_vars, name(), type_name(), msg))
00435         return false;
00436 
00437     if (all) {
00438         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00439             //assert(*i);
00440             if (!(*i)->check_semantics(msg, true)) {
00441                 status = false;
00442                 goto exit;
00443             }
00444         }
00445     }
00446 
00447 exit:
00448     return status;
00449 }
00450 
00459 void
00460 Structure::dump(ostream &strm) const
00461 {
00462     strm << DapIndent::LMarg << "Structure::dump - ("
00463     << (void *)this << ")" << endl ;
00464     DapIndent::Indent() ;
00465     Constructor::dump(strm) ;
00466     DapIndent::UnIndent() ;
00467 }
00468 

Generated on Wed Jun 27 12:56:39 2007 for libdap++ by  doxygen 1.4.7