Structure.cc
// -*- mode: c++; c-basic-offset:4 -*-
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.
// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
// (c) COPYRIGHT URI/MIT 1994-1999
// Please read the full copyright statement in the file COPYRIGHT_URI.
//
// Authors:
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
// Implementation for the class Structure
//
// jhrg 9/14/94
//#define DODS_DEBUG
#include "config.h"
#include <sstream>
#include "Byte.h"
#include "Int16.h"
#include "UInt16.h"
#include "Int32.h"
#include "UInt32.h"
#include "Float32.h"
#include "Float64.h"
#include "Str.h"
#include "Url.h"
#include "Array.h"
#include "Structure.h"
#include "Sequence.h"
#include "Grid.h"
#include "DDS.h"
#include "ConstraintEvaluator.h"
#include "D4Attributes.h"
#include "D4Group.h"
#include "XDRStreamMarshaller.h"
#include "util.h"
#include "debug.h"
#include "InternalErr.h"
#include "escaping.h"
#include "DapIndent.h"
using std::cerr;
using std::endl;
namespace libdap {
#if 0
void
Structure::m_duplicate(const Structure &s)
{
Constructor::m_duplicate(s);
#if 0
Structure &cs = const_cast<Structure &>(s);
DBG(cerr << "Copying structure: " << name() << endl);
for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) {
DBG(cerr << "Copying field: " << (*i)->name() << endl);
// Jose Garcia
// I think this assert here is part of a debugging
// process since it is going along with a DBG call
// I leave it here since it can be remove by defining NDEBUG.
// assert(*i);
BaseType *btp = (*i)->ptr_duplicate();
btp->set_parent(this);
d_vars.push_back(btp);
}
#endif
}
#endif
Structure::Structure(const string &n) : Constructor(n, dods_structure_c)
{}
Structure::Structure(const string &n, const string &d)
: Constructor(n, d, dods_structure_c)
{}
Structure::Structure(const Structure &rhs) : Constructor(rhs)
{
DBG(cerr << "In Structure::copy_ctor for " << name() << endl);
//m_duplicate(rhs);
}
Structure::~Structure()
{
}
BaseType *
Structure::ptr_duplicate()
{
return new Structure(*this);
}
void
Structure::transform_to_dap4(D4Group *root, Constructor *container)
{
DBG(cerr << __func__ <<"() - BEGIN" << endl;);
// Here we create a new Structure and then use it
// as the target container for the transformed versions of
// all the member variables by calling Constructor::transform_to_dap4() and
// passing our new target Structure in as the target container.
Structure *dest = new Structure(name());
DBG(cerr << __func__ <<"() - Calling Constructor::transform_to_dap4("<<
"'" << root->name() << "':" << (void*)root << ","
"'" << dest->name() << "':" << (void*)dest << ")"
<< endl; );
Constructor::transform_to_dap4(root, dest);
container->add_var_nocopy(dest);
DBG(cerr << __func__ <<"() - Added new Structure '" << dest->name() << "' (" << (void*)dest <<
") to the container '" << container->name() <<"'" << endl;);
DBG(cerr << __func__ <<"() - END"<< endl;);
}
vector<BaseType *> *
Structure::transform_to_dap2(AttrTable *)
{
DBG(cerr << " " << __func__ << " BEGIN" << endl);
Structure *dest = new Structure(name());
// convert the Structure's d4 attributes to a dap2 attribute table.
#if 0
AttrTable *attrs = this->attributes()->get_AttrTable(name());
#else
if (dest->get_attr_table().get_size() == 0) {
attributes()->transform_attrs_to_dap2(&dest->get_attr_table());
dest->get_attr_table().set_name(name());
}
#endif
dest->set_is_dap4(false);
vector<BaseType *> dropped_vars;
for (Structure::Vars_citer i = var_begin(), e = var_end(); i != e; ++i) {
vector<BaseType *> *new_vars = (*i)->transform_to_dap2(&dest->get_attr_table() /*attrs*/);
if (new_vars) { // Might be un-mappable
// It's not so game on..
#if 0
vector<BaseType*>::iterator vIter = new_vars->begin();
vector<BaseType*>::iterator end = new_vars->end();
#endif
for (vector<BaseType*>::iterator vi = new_vars->begin(), ve = new_vars->end(); vi != ve ; ++vi ) {
BaseType *new_var = (*vi);
new_var->set_parent(dest);
dest->add_var_nocopy(new_var);
(*vi) = NULL;
}
delete new_vars;
}
else {
// Got a NULL, so we are dropping this var.
dropped_vars.push_back(*i);
}
}
AttrTable *dv_attr_table = make_dropped_vars_attr_table(&dropped_vars);
if(dv_attr_table){
dest->get_attr_table().append_container(dv_attr_table,dv_attr_table->get_name());
}
DBG(attrs->print(cerr,"",true););
#if 0
// Since this does a copy we gotta delete the attrs when done
// FIXME This is a bug. jhrg 6/17/19
dest->set_attr_table(*attrs);
delete attrs;
#endif
vector<BaseType *> *result = new vector<BaseType *>();
result->push_back(dest);
DBG(cerr << " " << __func__ << " END" << endl);
return result;
}
Structure &
Structure::operator=(const Structure &rhs)
{
if (this == &rhs)
return *this;
Constructor::operator=(rhs);
return *this;
}
bool
Structure::is_linear()
{
bool linear = true;
for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) {
if ((*i)->type() == dods_structure_c)
linear = linear && static_cast<Structure*>((*i))->is_linear();
else
linear = linear && (*i)->is_simple_type();
}
return linear;
}
#if 0
void
Structure::set_send_p(bool state)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
(*i)->set_send_p(state);
}
BaseType::set_send_p(state);
}
void
Structure::set_read_p(bool state)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
(*i)->set_read_p(state);
}
BaseType::set_read_p(state);
}
#endif
#if 0
void
Structure::set_in_selection(bool state)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
(*i)->set_in_selection(state);
}
BaseType::set_in_selection(state);
}
#endif
void
Structure::set_leaf_sequence(int level)
{
for (Vars_iter i = var_begin(); i != var_end(); i++) {
if ((*i)->type() == dods_sequence_c)
static_cast<Sequence&>(**i).set_leaf_sequence(++level);
else if ((*i)->type() == dods_structure_c)
static_cast<Structure&>(**i).set_leaf_sequence(level);
}
}
#if 0
void
Structure::add_var(BaseType *bt, Part)
{
// Jose Garcia
// Passing and invalid pointer to an object is a developer's error.
if (!bt)
throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
if (bt->is_dap4_only_type())
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
// Jose Garcia
// Now we add a copy of bt so the external user is able to destroy bt as
// he/she wishes. The policy is: "If it is allocated outside, it is
// deallocated outside, if it is allocated inside, it is deallocated
// inside"
BaseType *btp = bt->ptr_duplicate();
btp->set_parent(this);
d_vars.push_back(btp);
}
void
Structure::add_var_nocopy(BaseType *bt, Part)
{
if (!bt)
throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
if (bt->is_dap4_only_type())
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
bt->set_parent(this);
d_vars.push_back(bt);
}
void
Structure::del_var(const string &n)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if ((*i)->name() == n) {
BaseType *bt = *i ;
d_vars.erase(i) ;
delete bt ; bt = 0;
return;
}
}
}
#endif
#if 0
bool Structure::read()
{
if (!read_p()) {
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
(*i)->read();
}
set_read_p(true);
}
return false;
}
#endif
#if 0
// TODO Recode to use width(bool)
unsigned int
Structure::width()
{
unsigned int sz = 0;
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
sz += (*i)->width();
}
return sz;
}
unsigned int
Structure::width(bool constrained)
{
unsigned int sz = 0;
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if (constrained) {
if ((*i)->send_p())
sz += (*i)->width(constrained);
}
else {
sz += (*i)->width(constrained);
}
}
return sz;
}
#endif
#if 0
void
Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
{
DBG(cerr << "Structure::intern_data: " << name() << endl);
if (!read_p())
read(); // read() throws Error and InternalErr
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if ((*i)->send_p()) {
(*i)->intern_data(eval, dds);
}
}
}
bool
Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
Marshaller &m, bool ce_eval)
{
#if USE_LOCAL_TIMEOUT_SCHEME
dds.timeout_on();
#endif
if (!read_p())
read(); // read() throws Error and InternalErr
#if EVAL
if (ce_eval && !eval.eval_selection(dds, dataset()))
return true;
#endif
#if USE_LOCAL_TIMEOUT_SCHEME
dds.timeout_off();
#endif
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if ((*i)->send_p()) {
#ifdef CHECKSUMS
XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
sm->reset_checksum();
(*i)->serialize(eval, dds, m, false);
if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
sm->get_checksum();
#else
(*i)->serialize(eval, dds, m, false);
#endif
}
}
return true;
}
bool
Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
(*i)->deserialize(um, dds, reuse);
}
return false;
}
#endif
#if 0
unsigned int
Structure::val2buf(void *, bool)
{
return sizeof(Structure);
}
unsigned int
Structure::buf2val(void **)
{
return sizeof(Structure);
}
#endif
#if 0
BaseType *
Structure::var(const string &name, bool exact_match, btp_stack *s)
{
string n = www2id(name);
if (exact_match)
return m_exact_match(n, s);
else
return m_leaf_match(n, s);
}
BaseType *
Structure::var(const string &n, btp_stack &s)
{
string name = www2id(n);
BaseType *btp = m_exact_match(name, &s);
if (btp)
return btp;
return m_leaf_match(name, &s);
}
#endif
#if 0
// Private method to find a variable using the shorthand name. This
// should be moved to Constructor.
BaseType *
Structure::m_leaf_match(const string &name, btp_stack *s)
{
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if ((*i)->name() == name) {
if (s) {
DBG(cerr << "Pushing " << this->name() << endl);
s->push(static_cast<BaseType *>(this));
}
return *i;
}
if ((*i)->is_constructor_type()) {
BaseType *btp = (*i)->var(name, false, s);
if (btp) {
if (s) {
DBG(cerr << "Pushing " << this->name() << endl);
s->push(static_cast<BaseType *>(this));
}
return btp;
}
}
}
return 0;
}
// Breadth-first search for NAME. If NAME contains one or more dots (.)
// TODO The btp_stack is not needed since there are 'back pointers' in
// BaseType.
BaseType *
Structure::m_exact_match(const string &name, btp_stack *s)
{
// Look for name at the top level first.
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
if ((*i)->name() == name) {
if (s)
s->push(static_cast<BaseType *>(this));
return *i;
}
}
// If it was not found using the simple search, look for a dot and
// search the hierarchy.
string::size_type dot_pos = name.find("."); // zero-based index of `.'
if (dot_pos != string::npos) {
string aggregate = name.substr(0, dot_pos);
string field = name.substr(dot_pos + 1);
BaseType *agg_ptr = var(aggregate);
if (agg_ptr) {
if (s)
s->push(static_cast<BaseType *>(this));
return agg_ptr->var(field, true, s); // recurse
}
else
return 0; // qualified names must be *fully* qualified
}
return 0;
}
#endif
#if 0
void
Structure::print_val(FILE *out, string space, bool print_decl_p)
{
ostringstream oss;
print_val(oss, space, print_decl_p);
fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
}
void
Structure::print_val(ostream &out, string space, bool print_decl_p)
{
if (print_decl_p) {
print_decl(out, space, false);
out << " = " ;
}
out << "{ " ;
for (Vars_citer i = d_vars.begin(); i != d_vars.end();
i++, (void)(i != d_vars.end() && out << ", ")) {
(*i)->print_val(out, "", false);
}
out << " }" ;
if (print_decl_p)
out << ";\n" ;
}
#endif
#if 0
bool
Structure::check_semantics(string &msg, bool all)
{
if (!BaseType::check_semantics(msg))
return false;
bool status = true;
if (!unique_names(d_vars, name(), type_name(), msg))
return false;
if (all) {
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
//assert(*i);
if (!(*i)->check_semantics(msg, true)) {
status = false;
goto exit;
}
}
}
exit:
return status;
}
#endif
void
Structure::dump(ostream &strm) const
{
strm << DapIndent::LMarg << "Structure::dump - ("
<< (void *)this << ")" << endl ;
DapIndent::Indent() ;
Constructor::dump(strm) ;
DapIndent::UnIndent() ;
}
} // namespace libdap
libdap::AttrTable
Contains the attributes for a dataset.
Definition AttrTable.h:154
libdap::AttrTable::append_container
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition AttrTable.cc:554
libdap::AttrTable::set_name
virtual void set_name(const string &n)
Set the name of this attribute table.
Definition AttrTable.cc:273
libdap::AttrTable::get_name
virtual string get_name() const
Get the name of this attribute table.
Definition AttrTable.cc:266
libdap::AttrTable::print
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
Definition AttrTable.cc:1432
libdap::AttrTable::get_size
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
Definition AttrTable.cc:259
libdap::BaseType
The basic data type for the DODS DAP types.
Definition BaseType.h:120
libdap::BaseType::m_duplicate
void m_duplicate(const BaseType &bt)
Perform a deep copy.
Definition BaseType.cc:86
libdap::BaseType::type_name
virtual string type_name() const
Returns the type of the class instance as a string.
Definition BaseType.cc:376
libdap::BaseType::intern_data
virtual void intern_data()
Read data into this variable.
Definition BaseType.cc:936
libdap::BaseType::read
virtual bool read()
Read data into a local buffer.
Definition BaseType.cc:905
libdap::BaseType::deserialize
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition BaseType.cc:949
libdap::BaseType::get_attr_table
virtual AttrTable & get_attr_table()
Definition BaseType.cc:579
libdap::BaseType::name
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:317
libdap::BaseType::set_in_selection
virtual void set_in_selection(bool state)
Definition BaseType.cc:715
libdap::BaseType::read_p
virtual bool read_p()
Has this variable been read?
Definition BaseType.cc:477
libdap::BaseType::width
virtual unsigned int width(bool constrained=false) const
How many bytes does this variable use Return the number of bytes of storage this variable uses....
Definition BaseType.cc:1305
libdap::BaseType::set_read_p
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition BaseType.cc:513
libdap::BaseType::dataset
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition BaseType.cc:355
libdap::BaseType::set_attr_table
virtual void set_attr_table(const AttrTable &at)
Definition BaseType.cc:587
libdap::BaseType::set_parent
virtual void set_parent(BaseType *parent)
Definition BaseType.cc:730
libdap::BaseType::attributes
virtual D4Attributes * attributes()
Definition BaseType.cc:596
libdap::BaseType::is_simple_type
virtual bool is_simple_type() const
Returns true if the instance is a numeric, string or URL type variable.
Definition BaseType.cc:390
libdap::BaseType::set_send_p
virtual void set_send_p(bool state)
Definition BaseType.cc:565
libdap::BaseType::ptr_duplicate
virtual BaseType * ptr_duplicate()=0
libdap::BaseType::val2buf
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
libdap::BaseType::buf2val
virtual unsigned int buf2val(void **val)=0
Reads the class data.
libdap::BaseType::serialize
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Move data to the net, then remove them from the object.
Definition BaseType.cc:943
libdap::BaseType::add_var
virtual void add_var(BaseType *bt, Part part=nil)
Add a variable.
Definition BaseType.cc:821
libdap::BaseType::check_semantics
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition BaseType.cc:1215
libdap::BaseType::BaseType
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition BaseType.cc:126
libdap::BaseType::var
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr)
Returns a pointer to a member of a constructor class.
Definition BaseType.cc:764
libdap::BaseType::print_val
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition BaseType.cc:1096
libdap::Constructor
Definition Constructor.h:44
libdap::Constructor::transform_to_dap4
void transform_to_dap4(D4Group *root, Constructor *dest) override
DAP2 to DAP4 transform.
Definition Constructor.cc:85
libdap::Constructor::var
BaseType * var(const string &name, bool exact_match=true, btp_stack *s=nullptr) override
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition Constructor.cc:210
libdap::Constructor::print_decl
void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false) override
Print an ASCII representation of the variable structure.
Definition Constructor.cc:588
libdap::Constructor::set_read_p
void set_read_p(bool state) override
Set the 'read_p' property for the Constructor and its members.
Definition Constructor.cc:151
libdap::Constructor::print_val
void print_val(FILE *out, string space="", bool print_decl_p=true) override
Prints the value of the variable.
Definition Constructor.cc:611
libdap::Constructor::var_end
Vars_iter var_end()
Definition Constructor.cc:305
libdap::Constructor::read
bool read() override
Read the elements of Constructor marked for transmission.
Definition Constructor.cc:447
libdap::Constructor::add_var_nocopy
void add_var_nocopy(BaseType *bt, Part part=nil) override
Definition Constructor.cc:395
libdap::Constructor::var_begin
Vars_iter var_begin()
Definition Constructor.cc:297
libdap::Constructor::del_var
virtual void del_var(const string &name)
Remove an element from a Constructor.
Definition Constructor.cc:416
libdap::Constructor::dump
void dump(ostream &strm) const override
dumps information about this object
Definition Constructor.cc:845
libdap::D4Attributes::transform_attrs_to_dap2
void transform_attrs_to_dap2(AttrTable *d2_attr_table)
Copy the attributes from this D4Attributes object to a DAP2 AttrTable.
Definition D4Attributes.cc:312
libdap::D4Group
Definition D4Group.h:44
libdap::InternalErr
A class for software fault reporting.
Definition InternalErr.h:65
libdap::Sequence
Holds a sequence.
Definition Sequence.h:163
libdap::Sequence::set_leaf_sequence
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition Sequence.cc:1240
libdap::Structure
Holds a structure (aggregate) type.
Definition Structure.h:84
libdap::Structure::Structure
Structure(const string &n)
Definition Structure.cc:110
libdap::Structure::dump
virtual void dump(ostream &strm) const
dumps information about this object
Definition Structure.cc:682
libdap::Structure::set_leaf_sequence
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition Structure.cc:309
libdap::Structure::transform_to_dap2
virtual vector< BaseType * > * transform_to_dap2(AttrTable *parent_attr_table)
DAP4 to DAP2 transform.
Definition Structure.cc:180
libdap::Structure::is_linear
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition Structure.cc:257
libdap::Structure::ptr_duplicate
virtual BaseType * ptr_duplicate()
Definition Structure.cc:138
libdap::Structure::transform_to_dap4
virtual void transform_to_dap4(D4Group *root, Constructor *container)
Definition Structure.cc:153
libdap
top level DAP object to house generic methods
Definition AlarmHandler.h:36
libdap::www2id
string www2id(const string &in, const string &escape, const string &except)
Definition escaping.cc:220
libdap::Part
Part
Names the parts of multi-section constructor data types.
Definition Type.h:48