libdap  Updated for version 3.17.0
Structure.cc
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  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 <sstream>
00041 
00042 #include "Byte.h"
00043 #include "Int16.h"
00044 #include "UInt16.h"
00045 #include "Int32.h"
00046 #include "UInt32.h"
00047 #include "Float32.h"
00048 #include "Float64.h"
00049 #include "Str.h"
00050 #include "Url.h"
00051 #include "Array.h"
00052 #include "Structure.h"
00053 #include "Sequence.h"
00054 #include "Grid.h"
00055 
00056 #include "DDS.h"
00057 #include "ConstraintEvaluator.h"
00058 
00059 #include "D4Attributes.h"
00060 #include "D4Group.h"
00061 
00062 #include "XDRStreamMarshaller.h"
00063 #include "util.h"
00064 #include "debug.h"
00065 #include "InternalErr.h"
00066 #include "escaping.h"
00067 
00068 using std::cerr;
00069 using std::endl;
00070 
00071 namespace libdap {
00072 
00073 #if 0
00074 
00078 void
00079 Structure::m_duplicate(const Structure &s)
00080 {
00081     Constructor::m_duplicate(s);
00082 #if 0
00083     Structure &cs = const_cast<Structure &>(s);
00084 
00085     DBG(cerr << "Copying structure: " << name() << endl);
00086 
00087     for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) {
00088         DBG(cerr << "Copying field: " << (*i)->name() << endl);
00089         // Jose Garcia
00090         // I think this assert here is part of a debugging
00091         // process since it is going along with a DBG call
00092         // I leave it here since it can be remove by defining NDEBUG.
00093         // assert(*i);
00094         BaseType *btp = (*i)->ptr_duplicate();
00095         btp->set_parent(this);
00096         d_vars.push_back(btp);
00097     }
00098 #endif
00099 }
00100 #endif
00101 
00109 Structure::Structure(const string &n) : Constructor(n, dods_structure_c)
00110 {}
00111 
00121 Structure::Structure(const string &n, const string &d)
00122     : Constructor(n, d, dods_structure_c)
00123 {}
00124 
00126 Structure::Structure(const Structure &rhs) : Constructor(rhs)
00127 {
00128     DBG(cerr << "In Structure::copy_ctor for " << name() << endl);
00129     //m_duplicate(rhs);
00130 }
00131 
00132 Structure::~Structure()
00133 {
00134 }
00135 
00136 BaseType *
00137 Structure::ptr_duplicate()
00138 {
00139     return new Structure(*this);
00140 }
00141 
00151 BaseType *
00152 Structure::transform_to_dap4(D4Group *root, Constructor *container)
00153 {
00154         // For this class, ptr_duplicate() calls the const ctor which calls
00155         // Constructor's const ctor which calls Constructor::m_duplicate().
00156         // Here we replicate some of that functionality, but instead call
00157         // transform_to_dap4() on the contained variables.
00158 
00159         // Structure *dest = static_cast<Structure*>(ptr_duplicate());
00160         Structure *dest = new Structure(name());
00161 
00162         Constructor::transform_to_dap4(root, dest);
00163         dest->set_parent(container);
00164 
00165         return dest;
00166 }
00167 
00168 Structure &
00169 Structure::operator=(const Structure &rhs)
00170 {
00171     DBG(cerr << "Entering Structure::operator=" << endl);
00172     if (this == &rhs)
00173         return *this;
00174 
00175     dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
00176 
00177     //m_duplicate(rhs);
00178 
00179     DBG(cerr << "Exiting Structure::operator=" << endl);
00180     return *this;
00181 }
00182 
00183 #if 0
00184 int
00185 Structure::element_count(bool leaves)
00186 {
00187     if (!leaves)
00188         return d_vars.size();
00189     else {
00190         int i = 0;
00191         for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
00192             i += (*j)->element_count(leaves);
00193         }
00194         return i;
00195     }
00196 }
00197 #endif
00198 
00199 bool
00200 Structure::is_linear()
00201 {
00202     bool linear = true;
00203     for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) {
00204         if ((*i)->type() == dods_structure_c)
00205             linear = linear && static_cast<Structure*>((*i))->is_linear();
00206         else
00207             linear = linear && (*i)->is_simple_type();
00208     }
00209 
00210     return linear;
00211 }
00212 
00213 #if 0
00214 void
00215 Structure::set_send_p(bool state)
00216 {
00217     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00218         (*i)->set_send_p(state);
00219     }
00220 
00221     BaseType::set_send_p(state);
00222 }
00223 
00224 void
00225 Structure::set_read_p(bool state)
00226 {
00227     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00228         (*i)->set_read_p(state);
00229     }
00230 
00231     BaseType::set_read_p(state);
00232 }
00233 #endif
00234 #if 0
00235 
00240 void
00241 Structure::set_in_selection(bool state)
00242 {
00243     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00244         (*i)->set_in_selection(state);
00245     }
00246 
00247     BaseType::set_in_selection(state);
00248 }
00249 #endif
00250 
00251 void
00252 Structure::set_leaf_sequence(int level)
00253 {
00254     for (Vars_iter i = var_begin(); i != var_end(); i++) {
00255         if ((*i)->type() == dods_sequence_c)
00256                 static_cast<Sequence&>(**i).set_leaf_sequence(++level);
00257         else if ((*i)->type() == dods_structure_c)
00258                 static_cast<Structure&>(**i).set_leaf_sequence(level);
00259     }
00260 }
00261 
00262 #if 0
00263 
00267 void
00268 Structure::add_var(BaseType *bt, Part)
00269 {
00270     // Jose Garcia
00271     // Passing and invalid pointer to an object is a developer's error.
00272     if (!bt)
00273         throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
00274 
00275     if (bt->is_dap4_only_type())
00276         throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
00277 
00278     // Jose Garcia
00279     // Now we add a copy of bt so the external user is able to destroy bt as
00280     // he/she wishes. The policy is: "If it is allocated outside, it is
00281     // deallocated outside, if it is allocated inside, it is deallocated
00282     // inside"
00283     BaseType *btp = bt->ptr_duplicate();
00284     btp->set_parent(this);
00285     d_vars.push_back(btp);
00286 }
00287 
00292 void
00293 Structure::add_var_nocopy(BaseType *bt, Part)
00294 {
00295     if (!bt)
00296         throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
00297 
00298     if (bt->is_dap4_only_type())
00299         throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
00300 
00301     bt->set_parent(this);
00302     d_vars.push_back(bt);
00303 }
00304 
00305 
00309 void
00310 Structure::del_var(const string &n)
00311 {
00312     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00313         if ((*i)->name() == n) {
00314             BaseType *bt = *i ;
00315             d_vars.erase(i) ;
00316             delete bt ; bt = 0;
00317             return;
00318         }
00319     }
00320 }
00321 #endif
00322 #if 0
00323 
00328 bool Structure::read()
00329 {
00330     if (!read_p()) {
00331         for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00332             (*i)->read();
00333         }
00334         set_read_p(true);
00335     }
00336 
00337     return false;
00338 }
00339 #endif
00340 #if 0
00341 // TODO Recode to use width(bool)
00342 unsigned int
00343 Structure::width()
00344 {
00345     unsigned int sz = 0;
00346 
00347     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00348         sz += (*i)->width();
00349     }
00350 
00351     return sz;
00352 }
00353 
00361 unsigned int
00362 Structure::width(bool constrained)
00363 {
00364     unsigned int sz = 0;
00365 
00366     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00367         if (constrained) {
00368                 if ((*i)->send_p())
00369                         sz += (*i)->width(constrained);
00370         }
00371         else {
00372                 sz += (*i)->width(constrained);
00373         }
00374     }
00375 
00376     return sz;
00377 }
00378 #endif
00379 
00380 #if 0
00381 void
00382 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
00383 {
00384     DBG(cerr << "Structure::intern_data: " << name() << endl);
00385     if (!read_p())
00386         read();          // read() throws Error and InternalErr
00387 
00388     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00389         if ((*i)->send_p()) {
00390             (*i)->intern_data(eval, dds);
00391         }
00392     }
00393 }
00394 
00395 bool
00396 Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
00397                      Marshaller &m, bool ce_eval)
00398 {
00399 #if USE_LOCAL_TIMEOUT_SCHEME
00400     dds.timeout_on();
00401 #endif
00402     if (!read_p())
00403         read();  // read() throws Error and InternalErr
00404 
00405 #if EVAL
00406     if (ce_eval && !eval.eval_selection(dds, dataset()))
00407         return true;
00408 #endif
00409 #if USE_LOCAL_TIMEOUT_SCHEME
00410     dds.timeout_off();
00411 #endif
00412     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00413         if ((*i)->send_p()) {
00414 #ifdef CHECKSUMS
00415             XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
00416             if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
00417                 sm->reset_checksum();
00418 
00419             (*i)->serialize(eval, dds, m, false);
00420 
00421             if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
00422                 sm->get_checksum();
00423 #else
00424             (*i)->serialize(eval, dds, m, false);
00425 #endif
00426         }
00427     }
00428 
00429     return true;
00430 }
00431 
00432 bool
00433 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
00434 {
00435     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00436         (*i)->deserialize(um, dds, reuse);
00437     }
00438 
00439     return false;
00440 }
00441 #endif
00442 #if 0
00443 
00452 unsigned int
00453 Structure::val2buf(void *, bool)
00454 {
00455     return sizeof(Structure);
00456 }
00457 
00461 unsigned int
00462 Structure::buf2val(void **)
00463 {
00464     return sizeof(Structure);
00465 }
00466 #endif
00467 
00468 #if 0
00469 BaseType *
00470 Structure::var(const string &name, bool exact_match, btp_stack *s)
00471 {
00472     string n = www2id(name);
00473 
00474     if (exact_match)
00475         return m_exact_match(n, s);
00476     else
00477         return m_leaf_match(n, s);
00478 }
00479 
00481 BaseType *
00482 Structure::var(const string &n, btp_stack &s)
00483 {
00484     string name = www2id(n);
00485 
00486     BaseType *btp = m_exact_match(name, &s);
00487     if (btp)
00488         return btp;
00489 
00490     return m_leaf_match(name, &s);
00491 }
00492 #endif
00493 #if 0
00494 // Private method to find a variable using the shorthand name. This
00495 // should be moved to Constructor.
00496 BaseType *
00497 Structure::m_leaf_match(const string &name, btp_stack *s)
00498 {
00499     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00500         if ((*i)->name() == name) {
00501             if (s) {
00502                 DBG(cerr << "Pushing " << this->name() << endl);
00503                 s->push(static_cast<BaseType *>(this));
00504             }
00505             return *i;
00506         }
00507         if ((*i)->is_constructor_type()) {
00508             BaseType *btp = (*i)->var(name, false, s);
00509             if (btp) {
00510                 if (s) {
00511                     DBG(cerr << "Pushing " << this->name() << endl);
00512                     s->push(static_cast<BaseType *>(this));
00513                 }
00514                 return btp;
00515             }
00516         }
00517     }
00518 
00519     return 0;
00520 }
00521 
00522 // Breadth-first search for NAME. If NAME contains one or more dots (.)
00523 // TODO The btp_stack is not needed since there are 'back pointers' in
00524 // BaseType.
00525 BaseType *
00526 Structure::m_exact_match(const string &name, btp_stack *s)
00527 {
00528     // Look for name at the top level first.
00529     for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00530         if ((*i)->name() == name) {
00531             if (s)
00532                 s->push(static_cast<BaseType *>(this));
00533 
00534             return *i;
00535         }
00536     }
00537 
00538     // If it was not found using the simple search, look for a dot and
00539     // search the hierarchy.
00540     string::size_type dot_pos = name.find("."); // zero-based index of `.'
00541     if (dot_pos != string::npos) {
00542         string aggregate = name.substr(0, dot_pos);
00543         string field = name.substr(dot_pos + 1);
00544 
00545         BaseType *agg_ptr = var(aggregate);
00546         if (agg_ptr) {
00547             if (s)
00548                 s->push(static_cast<BaseType *>(this));
00549 
00550             return agg_ptr->var(field, true, s); // recurse
00551         }
00552         else
00553             return 0;  // qualified names must be *fully* qualified
00554     }
00555 
00556     return 0;
00557 }
00558 #endif
00559 #if 0
00560 void
00561 Structure::print_val(FILE *out, string space, bool print_decl_p)
00562 {
00563     ostringstream oss;
00564     print_val(oss, space, print_decl_p);
00565     fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
00566 }
00567 
00568 void
00569 Structure::print_val(ostream &out, string space, bool print_decl_p)
00570 {
00571     if (print_decl_p) {
00572         print_decl(out, space, false);
00573         out << " = " ;
00574     }
00575 
00576     out << "{ " ;
00577     for (Vars_citer i = d_vars.begin(); i != d_vars.end();
00578          i++, (void)(i != d_vars.end() && out << ", ")) {
00579         (*i)->print_val(out, "", false);
00580     }
00581 
00582     out << " }" ;
00583 
00584     if (print_decl_p)
00585         out << ";\n" ;
00586 }
00587 #endif
00588 
00589 #if 0
00590 bool
00591 Structure::check_semantics(string &msg, bool all)
00592 {
00593     if (!BaseType::check_semantics(msg))
00594         return false;
00595 
00596     bool status = true;
00597 
00598     if (!unique_names(d_vars, name(), type_name(), msg))
00599         return false;
00600 
00601     if (all) {
00602         for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
00603             //assert(*i);
00604             if (!(*i)->check_semantics(msg, true)) {
00605                 status = false;
00606                 goto exit;
00607             }
00608         }
00609     }
00610 
00611 exit:
00612     return status;
00613 }
00614 #endif
00615 
00624 void
00625 Structure::dump(ostream &strm) const
00626 {
00627     strm << DapIndent::LMarg << "Structure::dump - ("
00628     << (void *)this << ")" << endl ;
00629     DapIndent::Indent() ;
00630     Constructor::dump(strm) ;
00631     DapIndent::UnIndent() ;
00632 }
00633 
00634 } // namespace libdap
00635