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 // Jose Garcia 1/26/2000
00051 // Note: all asserts of nature
00052 // for (Pix p = _vars.first(); p; _vars.next(p)) {
00053 //  assert(_vars(p));
00054 // had been commented out, later when we get sure
00055 // we do not need then we can remove them all.
00056 
00057 void
00058 Structure::_duplicate(const Structure &s)
00059 {
00060     Structure &cs = const_cast<Structure &>(s);
00061 
00062     DBG(cerr << "Copying strucutre: " << name() << endl);
00063 
00064     for (Vars_iter i = cs._vars.begin(); i != cs._vars.end(); i++) {
00065         DBG(cerr << "Copying field: " << cs.name() << endl);
00066         // Jose Garcia
00067         // I think this assert here is part of a debugging
00068         // process since it is going along with a DBG call
00069         // I leave it here since it can be remove by defining NDEBUG.
00070         // assert(*i);
00071         BaseType *btp = (*i)->ptr_duplicate();
00072         btp->set_parent(this);
00073         _vars.push_back(btp);
00074     }
00075 }
00076 
00084 Structure::Structure(const string &n) : Constructor(n, dods_structure_c)
00085 {}
00086 
00088 Structure::Structure(const Structure &rhs) : Constructor(rhs)
00089 {
00090     _duplicate(rhs);
00091 }
00092 
00093 Structure::~Structure()
00094 {
00095     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00096         BaseType *btp = *i ;
00097         delete btp ;  btp = 0;
00098     }
00099 }
00100 
00101 BaseType *
00102 Structure::ptr_duplicate()
00103 {
00104     return new Structure(*this);
00105 }
00106 
00107 Structure &
00108 Structure::operator=(const Structure &rhs)
00109 {
00110     if (this == &rhs)
00111         return *this;
00112 
00113     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00114 
00115     _duplicate(rhs);
00116 
00117     return *this;
00118 }
00119 
00120 int
00121 Structure::element_count(bool leaves)
00122 {
00123     if (!leaves)
00124         return _vars.size();
00125     else {
00126         int i = 0;
00127         for (Vars_iter j = _vars.begin(); j != _vars.end(); j++) {
00128             j += (*j)->element_count(leaves);
00129         }
00130         return i;
00131     }
00132 }
00133 
00134 bool
00135 Structure::is_linear()
00136 {
00137     bool linear = true;
00138     for (Vars_iter i = _vars.begin(); linear && i != _vars.end(); i++) {
00139         if ((*i)->type() == dods_structure_c)
00140             linear = linear && dynamic_cast<Structure*>((*i))->is_linear();
00141         else
00142             linear = linear && (*i)->is_simple_type();
00143     }
00144 
00145     return linear;
00146 }
00147 
00148 void
00149 Structure::set_send_p(bool state)
00150 {
00151     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00152         //assert(*i);
00153         (*i)->set_send_p(state);
00154     }
00155 
00156     BaseType::set_send_p(state);
00157 }
00158 
00159 void
00160 Structure::set_read_p(bool state)
00161 {
00162     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00163         //assert(*i);
00164         (*i)->set_read_p(state);
00165     }
00166 
00167     BaseType::set_read_p(state);
00168 }
00169 
00175 void
00176 Structure::set_in_selection(bool state)
00177 {
00178     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00179         (*i)->set_in_selection(state);
00180     }
00181 
00182     BaseType::set_in_selection(state);
00183 }
00184 
00186 void
00187 Structure::set_leaf_sequence(int level)
00188 {
00189     for (Vars_iter i = var_begin(); i != var_end(); i++) {
00190         if ((*i)->type() == dods_sequence_c)
00191             dynamic_cast<Sequence&>(**i).set_leaf_sequence(++level);
00192         else if ((*i)->type() == dods_structure_c)
00193             dynamic_cast<Structure&>(**i).set_leaf_sequence(level);
00194     }
00195 }
00196 
00197 // NB: Part defaults to nil for this class
00198 
00203 void
00204 Structure::add_var(BaseType *bt, Part)
00205 {
00206     // Jose Garcia
00207     // Passing and invalid pointer to an object is a developer's error.
00208     if (!bt)
00209         throw InternalErr(__FILE__, __LINE__,
00210                           "The BaseType parameter cannot be null.");
00211 
00212     // Jose Garcia
00213     // Now we add a copy of bt so the external user is able to destroy bt as
00214     // he/she whishes. The policy is: "If it is allocated outside, it is
00215     // deallocated outside, if it is allocated inside, it is deallocated
00216     // inside"
00217     BaseType *btp = bt->ptr_duplicate();
00218     btp->set_parent(this);
00219     _vars.push_back(btp);
00220 }
00221 
00222 unsigned int
00223 Structure::width()
00224 {
00225     unsigned int sz = 0;
00226 
00227     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00228         sz += (*i)->width();
00229     }
00230 
00231     return sz;
00232 }
00233 
00234 void
00235 Structure::transfer_data(const string & dataset,
00236                          ConstraintEvaluator & eval, DDS & dds)
00237 {
00238     if (!read_p())
00239         read(dataset);          // read() throws Error and InternalErr
00240 
00241     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00242         if ((*i)->send_p()) {
00243             switch ((*i)->type()) {
00244             case dods_sequence_c:
00245                 dynamic_cast <Sequence & >(**i).transfer_data(dataset,
00246                         eval, dds);
00247                 break;
00248 
00249             case dods_structure_c:
00250                 dynamic_cast <Structure & >(**i).transfer_data(dataset,
00251                         eval, dds);
00252                 break;
00253 
00254             default:
00255                 (*i)->read(dataset);
00256                 break;
00257             }
00258         }
00259     }
00260 }
00261 
00262 // Returns: false if an error was detected, true otherwise.
00263 // NB: this means that serialize() returns true when the CE evaluates to
00264 // false. This bug might be fixed using exceptions.
00265 
00266 bool
00267 Structure::serialize(const string &dataset, ConstraintEvaluator &eval, DDS &dds,
00268                      XDR *sink, bool ce_eval)
00269 {
00270     dds.timeout_on();
00271 
00272     if (!read_p())
00273         read(dataset);  // read() throws Error and InternalErr
00274 
00275 #if EVAL
00276     if (ce_eval && !eval.eval_selection(dds, dataset))
00277         return true;
00278 #endif
00279     dds.timeout_off();
00280 
00281     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00282         if ((*i)->send_p()) {
00283             (*i)->serialize(dataset, eval, dds, sink, false);
00284         }
00285     }
00286 
00287     return true;
00288 }
00289 
00290 bool
00291 Structure::deserialize(XDR *source, DDS *dds, bool reuse)
00292 {
00293     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00294         (*i)->deserialize(source, dds, reuse);
00295     }
00296 
00297     return false;
00298 }
00299 
00303 unsigned int
00304 Structure::val2buf(void *, bool)
00305 {
00306     return sizeof(Structure);
00307 }
00308 
00310 unsigned int
00311 Structure::buf2val(void **)
00312 {
00313     return sizeof(Structure);
00314 }
00315 
00316 // If EXACT is true, then use breadth-first search and assume that NAME is
00317 // the path to a variable where a dot (.) separates the ctor variable(s) from
00318 // the variable to be found. If S is not null, push the path to NAME on the
00319 // statck.
00320 BaseType *
00321 Structure::var(const string &name, bool exact_match, btp_stack *s)
00322 {
00323     string n = www2id(name);
00324 
00325     if (exact_match)
00326         return m_exact_match(n, s);
00327     else
00328         return m_leaf_match(n, s);
00329 }
00330 
00331 // Get rid of this method ASAP.
00332 // A depth-first search for leaf nodes matching NAME.
00333 BaseType *
00334 Structure::var(const string &n, btp_stack &s)
00335 {
00336     string name = www2id(n);
00337 
00338     BaseType *btp = m_exact_match(name, &s);
00339     if (btp)
00340         return btp;
00341 
00342     return m_leaf_match(name, &s);
00343 }
00344 
00345 // If S is not null, push the path of the depth-first search for a
00346 // leaf-node called NAME onto S.
00347 BaseType *
00348 Structure::m_leaf_match(const string &name, btp_stack *s)
00349 {
00350     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00351         if ((*i)->name() == name) {
00352             if (s) {
00353                 DBG(cerr << "Pushing " << this->name() << endl);
00354                 s->push(static_cast<BaseType *>(this));
00355             }
00356             return *i;
00357         }
00358         if ((*i)->is_constructor_type()) {
00359             BaseType *btp = (*i)->var(name, false, s);
00360             if (btp) {
00361                 if (s) {
00362                     DBG(cerr << "Pushing " << this->name() << endl);
00363                     s->push(static_cast<BaseType *>(this));
00364                 }
00365                 return btp;
00366             }
00367         }
00368     }
00369 
00370     return 0;
00371 }
00372 
00374 BaseType *
00375 Structure::m_exact_match(const string &name, btp_stack *s)
00376 {
00377     for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00378         DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i
00379             << endl);
00380         if ((*i)->name() == name) {
00381             DBG(cerr << "Found " << (*i)->name() << " in: "
00382                 << *i << endl);
00383             if (s) {
00384                 DBG(cerr << "Pushing " << this->name() << endl);
00385                 s->push(static_cast<BaseType *>(this));
00386             }
00387             return *i;
00388         }
00389     }
00390 
00391     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00392     if (dot_pos != string::npos) {
00393         string aggregate = name.substr(0, dot_pos);
00394         string field = name.substr(dot_pos + 1);
00395 
00396         BaseType *agg_ptr = var(aggregate);
00397         if (agg_ptr) {
00398             DBG(cerr << "Descending into " << agg_ptr->name() << endl);
00399             if (s) {
00400                 DBG(cerr << "Pushing " << this->name() << endl);
00401                 s->push(static_cast<BaseType *>(this));
00402             }
00403             return agg_ptr->var(field, true, s); // recurse
00404         }
00405         else
00406             return 0;  // qualified names must be *fully* qualified
00407     }
00408 
00409     return 0;
00410 }
00411 
00412 void
00413 Structure::print_val(FILE *out, string space, bool print_decl_p)
00414 {
00415     if (print_decl_p) {
00416         print_decl(out, space, false);
00417         fprintf(out, " = ") ;
00418     }
00419 
00420     fprintf(out, "{ ") ;
00421     for (Vars_citer i = _vars.begin(); i != _vars.end();
00422          i++, (void)(i != _vars.end() && fprintf(out, ", "))) {
00423         (*i)->print_val(out, "", false);
00424     }
00425 
00426     fprintf(out, " }") ;
00427 
00428     if (print_decl_p)
00429         fprintf(out, ";\n") ;
00430 }
00431 
00432 void
00433 Structure::print_all_vals(FILE *out, XDR *, DDS *, string space, bool print_decl_p)
00434 {
00435     print_val(out, space, print_decl_p);
00436 }
00437 
00438 bool
00439 Structure::check_semantics(string &msg, bool all)
00440 {
00441     if (!BaseType::check_semantics(msg))
00442         return false;
00443 
00444     bool status = true;
00445 
00446     if (!unique_names(_vars, name(), type_name(), msg))
00447         return false;
00448 
00449     if (all) {
00450         for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
00451             //assert(*i);
00452             if (!(*i)->check_semantics(msg, true)) {
00453                 status = false;
00454                 goto exit;
00455             }
00456         }
00457     }
00458 
00459 exit:
00460     return status;
00461 }
00462 
00471 void
00472 Structure::dump(ostream &strm) const
00473 {
00474     strm << DapIndent::LMarg << "Structure::dump - ("
00475     << (void *)this << ")" << endl ;
00476     DapIndent::Indent() ;
00477     Constructor::dump(strm) ;
00478     DapIndent::UnIndent() ;
00479 }
00480 

Generated on Fri Feb 8 05:14:03 2008 for libdap++ by  doxygen 1.5.4