|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2002,2003 OPeNDAP, Inc.
|
|
Packit |
a4aae4 |
// Author: James Gallagher <jgallagher@opendap.org>
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is free software; you can redistribute it and/or
|
|
Packit |
a4aae4 |
// modify it under the terms of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License as published by the Free Software Foundation; either
|
|
Packit |
a4aae4 |
// version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// This library is distributed in the hope that it will be useful,
|
|
Packit |
a4aae4 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
a4aae4 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
a4aae4 |
// Lesser General Public License for more details.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You should have received a copy of the GNU Lesser General Public
|
|
Packit |
a4aae4 |
// License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// (c) COPYRIGHT URI/MIT 1994-1999
|
|
Packit |
a4aae4 |
// Please read the full copyright statement in the file COPYRIGHT_URI.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Authors:
|
|
Packit |
a4aae4 |
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Implementation for the class Structure
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// jhrg 9/14/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#define DODS_DEBUG
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Byte.h"
|
|
Packit |
a4aae4 |
#include "Int16.h"
|
|
Packit |
a4aae4 |
#include "UInt16.h"
|
|
Packit |
a4aae4 |
#include "Int32.h"
|
|
Packit |
a4aae4 |
#include "UInt32.h"
|
|
Packit |
a4aae4 |
#include "Float32.h"
|
|
Packit |
a4aae4 |
#include "Float64.h"
|
|
Packit |
a4aae4 |
#include "Str.h"
|
|
Packit |
a4aae4 |
#include "Url.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Structure.h"
|
|
Packit |
a4aae4 |
#include "Sequence.h"
|
|
Packit |
a4aae4 |
#include "Grid.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "DDS.h"
|
|
Packit |
a4aae4 |
#include "ConstraintEvaluator.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "D4Attributes.h"
|
|
Packit |
a4aae4 |
#include "D4Group.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "XDRStreamMarshaller.h"
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
/** This method is protected so it's hidden from the whole world, but
|
|
Packit |
a4aae4 |
* available to direct child classes. Because of that, we need a glue-routine
|
|
Packit |
a4aae4 |
* here so children of Structure can specialize it.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::m_duplicate(const Structure &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Constructor::m_duplicate(s);
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
Structure &cs = const_cast<Structure &>(s);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Copying structure: " << name() << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Copying field: " << (*i)->name() << endl);
|
|
Packit |
a4aae4 |
// Jose Garcia
|
|
Packit |
a4aae4 |
// I think this assert here is part of a debugging
|
|
Packit |
a4aae4 |
// process since it is going along with a DBG call
|
|
Packit |
a4aae4 |
// I leave it here since it can be remove by defining NDEBUG.
|
|
Packit |
a4aae4 |
// assert(*i);
|
|
Packit |
a4aae4 |
BaseType *btp = (*i)->ptr_duplicate();
|
|
Packit |
a4aae4 |
btp->set_parent(this);
|
|
Packit |
a4aae4 |
d_vars.push_back(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The Structure constructor requires only the name of the variable
|
|
Packit |
a4aae4 |
to be created. The name may be omitted, which will create a
|
|
Packit |
a4aae4 |
nameless variable. This may be adequate for some applications.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n A string containing the name of the variable to be
|
|
Packit |
a4aae4 |
created.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
Structure::Structure(const string &n) : Constructor(n, dods_structure_c)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The Structure server-side constructor requires the name of the variable
|
|
Packit |
a4aae4 |
to be created and the dataset name from which this variable is being
|
|
Packit |
a4aae4 |
created. Used on server-side handlers.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n A string containing the name of the variable to be
|
|
Packit |
a4aae4 |
created.
|
|
Packit |
a4aae4 |
@param d A string containing the name of the dataset from which this
|
|
Packit |
a4aae4 |
variable is being created.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
Structure::Structure(const string &n, const string &d)
|
|
Packit |
a4aae4 |
: Constructor(n, d, dods_structure_c)
|
|
Packit |
a4aae4 |
{}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** The Structure copy constructor. */
|
|
Packit |
a4aae4 |
Structure::Structure(const Structure &rhs) : Constructor(rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "In Structure::copy_ctor for " << name() << endl);
|
|
Packit |
a4aae4 |
//m_duplicate(rhs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Structure::~Structure()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
Structure::ptr_duplicate()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return new Structure(*this);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* Build a DAP4 Structure.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* This code must be subclassed for all but the most trivial cases.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param root
|
|
Packit |
a4aae4 |
* @param container
|
|
Packit |
a4aae4 |
* @return The new variable
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::transform_to_dap4(D4Group *root, Constructor *container)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ <<"() - BEGIN" << endl;);
|
|
Packit |
a4aae4 |
// Here we create a new Structure and then use it
|
|
Packit |
a4aae4 |
// as the target container for the transformed versions of
|
|
Packit |
a4aae4 |
// all the member variables by calling Constructor::transform_to_dap4() and
|
|
Packit |
a4aae4 |
// passing our new target Structure in as the target container.
|
|
Packit |
a4aae4 |
Structure *dest = new Structure(name());
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ <<"() - Calling Constructor::transform_to_dap4("<<
|
|
Packit |
a4aae4 |
"'" << root->name() << "':" << (void*)root << ","
|
|
Packit |
a4aae4 |
"'" << dest->name() << "':" << (void*)dest << ")"
|
|
Packit |
a4aae4 |
<< endl; );
|
|
Packit |
a4aae4 |
Constructor::transform_to_dap4(root, dest);
|
|
Packit |
a4aae4 |
container->add_var_nocopy(dest);
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ <<"() - Added new Structure '" << dest->name() << "' (" << (void*)dest <<
|
|
Packit |
a4aae4 |
") to the container '" << container->name() <<"'" << endl;);
|
|
Packit |
a4aae4 |
DBG(cerr << __func__ <<"() - END"<< endl;);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief DAP4 to DAP2 transform
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Return a DAP2 'copy' of the variable.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @return A pointer to the transformed variable
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
vector<BaseType *> *
|
|
Packit |
a4aae4 |
Structure::transform_to_dap2(AttrTable *)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << " " << __func__ << " BEGIN" << endl);
|
|
Packit |
a4aae4 |
Structure *dest = new Structure(name());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// convert the Structure's d4 attributes to a dap2 attribute table.
|
|
Packit |
a4aae4 |
AttrTable *attrs = this->attributes()->get_AttrTable(name());
|
|
Packit |
a4aae4 |
dest->set_is_dap4(false);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *> dropped_vars;
|
|
Packit |
a4aae4 |
for (Structure::Vars_citer i = var_begin(), e = var_end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
vector<BaseType *> *new_vars = (*i)->transform_to_dap2(attrs);
|
|
Packit |
a4aae4 |
if (new_vars) { // Might be un-mappable
|
|
Packit |
a4aae4 |
// It's not so game on..
|
|
Packit |
a4aae4 |
vector<BaseType*>::iterator vIter = new_vars->begin();
|
|
Packit |
a4aae4 |
vector<BaseType*>::iterator end = new_vars->end();
|
|
Packit |
a4aae4 |
for( ; vIter!=end ; vIter++ ){
|
|
Packit |
a4aae4 |
BaseType *new_var = (*vIter);
|
|
Packit |
a4aae4 |
new_var->set_parent(dest);
|
|
Packit |
a4aae4 |
dest->add_var_nocopy(new_var);
|
|
Packit |
a4aae4 |
(*vIter) = NULL;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
delete new_vars;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
// Got a NULL, so we are dropping this var.
|
|
Packit |
a4aae4 |
dropped_vars.push_back(*i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable *dv_attr_table = make_dropped_vars_attr_table(&dropped_vars);
|
|
Packit |
a4aae4 |
if(dv_attr_table){
|
|
Packit |
a4aae4 |
DBG(cerr << " " << __func__ << "() - Adding "<< dv_attr_table->get_name() << " AttrTable" << endl);
|
|
Packit |
a4aae4 |
attrs->append_container(dv_attr_table,dv_attr_table->get_name());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
DBG(attrs->print(cerr,"",true););
|
|
Packit |
a4aae4 |
// Since this does a copy we gotta delete the attrs when done
|
|
Packit |
a4aae4 |
dest->set_attr_table(*attrs);
|
|
Packit |
a4aae4 |
delete attrs;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<BaseType *> *result = new vector<BaseType *>();
|
|
Packit |
a4aae4 |
result->push_back(dest);
|
|
Packit |
a4aae4 |
DBG(cerr << " " << __func__ << " END" << endl);
|
|
Packit |
a4aae4 |
return result;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Structure &
|
|
Packit |
a4aae4 |
Structure::operator=(const Structure &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering Structure::operator=" << endl);
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//m_duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Exiting Structure::operator=" << endl);
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
Structure::element_count(bool leaves)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!leaves)
|
|
Packit |
a4aae4 |
return d_vars.size();
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
int i = 0;
|
|
Packit |
a4aae4 |
for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
|
|
Packit |
a4aae4 |
i += (*j)->element_count(leaves);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
Structure::is_linear()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
bool linear = true;
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->type() == dods_structure_c)
|
|
Packit |
a4aae4 |
linear = linear && static_cast<Structure*>((*i))->is_linear();
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
linear = linear && (*i)->is_simple_type();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return linear;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::set_send_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->set_send_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType::set_send_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::set_read_p(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->set_read_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType::set_read_p(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
/** Set the \e in_selection property for this variable and all of its
|
|
Packit |
a4aae4 |
children.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Set the \e in_selection property.
|
|
Packit |
a4aae4 |
@param state Set the property value to \e state. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::set_in_selection(bool state)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->set_in_selection(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType::set_in_selection(state);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
/** @brief Traverse Structure, set Sequence leaf nodes. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::set_leaf_sequence(int level)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = var_begin(); i != var_end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->type() == dods_sequence_c)
|
|
Packit |
a4aae4 |
static_cast<Sequence&>(**i).set_leaf_sequence(++level);
|
|
Packit |
a4aae4 |
else if ((*i)->type() == dods_structure_c)
|
|
Packit |
a4aae4 |
static_cast<Structure&>(**i).set_leaf_sequence(level);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
/** Adds an element to a Structure.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param bt A pointer to the DAP2 type variable to add to this Structure.
|
|
Packit |
a4aae4 |
@param part Not used by this class, defaults to nil */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::add_var(BaseType *bt, Part)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Jose Garcia
|
|
Packit |
a4aae4 |
// Passing and invalid pointer to an object is a developer's error.
|
|
Packit |
a4aae4 |
if (!bt)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (bt->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Jose Garcia
|
|
Packit |
a4aae4 |
// Now we add a copy of bt so the external user is able to destroy bt as
|
|
Packit |
a4aae4 |
// he/she wishes. The policy is: "If it is allocated outside, it is
|
|
Packit |
a4aae4 |
// deallocated outside, if it is allocated inside, it is deallocated
|
|
Packit |
a4aae4 |
// inside"
|
|
Packit |
a4aae4 |
BaseType *btp = bt->ptr_duplicate();
|
|
Packit |
a4aae4 |
btp->set_parent(this);
|
|
Packit |
a4aae4 |
d_vars.push_back(btp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Adds an element to a Structure.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param bt A pointer to the DAP2 type variable to add to this Structure.
|
|
Packit |
a4aae4 |
@param part Not used by this class, defaults to nil */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::add_var_nocopy(BaseType *bt, Part)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!bt)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (bt->is_dap4_only_type())
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bt->set_parent(this);
|
|
Packit |
a4aae4 |
d_vars.push_back(bt);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Removed an element from a Structure.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param n name of the variable to remove */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::del_var(const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->name() == n) {
|
|
Packit |
a4aae4 |
BaseType *bt = *i ;
|
|
Packit |
a4aae4 |
d_vars.erase(i) ;
|
|
Packit |
a4aae4 |
delete bt ; bt = 0;
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
/** @brief simple implementation of read that iterates through vars
|
|
Packit |
a4aae4 |
* and calls read on them
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @return returns false to signify all has been read
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool Structure::read()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!read_p()) {
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->read();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
set_read_p(true);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// TODO Recode to use width(bool)
|
|
Packit |
a4aae4 |
unsigned int
|
|
Packit |
a4aae4 |
Structure::width()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
unsigned int sz = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
sz += (*i)->width();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return sz;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This version of width simply returns the same thing as width() for simple
|
|
Packit |
a4aae4 |
types and Arrays. For Structure it returns the total size if constrained
|
|
Packit |
a4aae4 |
is false, or the size of the elements in the current projection if true.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param constrained If true, return the size after applying a constraint.
|
|
Packit |
a4aae4 |
@return The number of bytes used by the variable.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
unsigned int
|
|
Packit |
a4aae4 |
Structure::width(bool constrained)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
unsigned int sz = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if (constrained) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p())
|
|
Packit |
a4aae4 |
sz += (*i)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
sz += (*i)->width(constrained);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return sz;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Structure::intern_data: " << name() << endl);
|
|
Packit |
a4aae4 |
if (!read_p())
|
|
Packit |
a4aae4 |
read(); // read() throws Error and InternalErr
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p()) {
|
|
Packit |
a4aae4 |
(*i)->intern_data(eval, dds);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
|
|
Packit |
a4aae4 |
Marshaller &m, bool ce_eval)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
dds.timeout_on();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
if (!read_p())
|
|
Packit |
a4aae4 |
read(); // read() throws Error and InternalErr
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if EVAL
|
|
Packit |
a4aae4 |
if (ce_eval && !eval.eval_selection(dds, dataset()))
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if USE_LOCAL_TIMEOUT_SCHEME
|
|
Packit |
a4aae4 |
dds.timeout_off();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->send_p()) {
|
|
Packit |
a4aae4 |
#ifdef CHECKSUMS
|
|
Packit |
a4aae4 |
XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
|
|
Packit |
a4aae4 |
if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
|
|
Packit |
a4aae4 |
sm->reset_checksum();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
(*i)->serialize(eval, dds, m, false);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
|
|
Packit |
a4aae4 |
sm->get_checksum();
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
(*i)->serialize(eval, dds, m, false);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
(*i)->deserialize(um, dds, reuse);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
/** @brief Never call this
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This method cannot be used to change values of a Structure since
|
|
Packit |
a4aae4 |
the values of a Constructor type must be set using methods in
|
|
Packit |
a4aae4 |
Constructor. See the Constructor::var_begin() and related
|
|
Packit |
a4aae4 |
methods.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@todo Make this throw an exception
|
|
Packit |
a4aae4 |
@return Returns the size of the structure. */
|
|
Packit |
a4aae4 |
unsigned int
|
|
Packit |
a4aae4 |
Structure::val2buf(void *, bool)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return sizeof(Structure);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Never call this
|
|
Packit |
a4aae4 |
@see val2buf()
|
|
Packit |
a4aae4 |
@return Returns the size of the structure. */
|
|
Packit |
a4aae4 |
unsigned int
|
|
Packit |
a4aae4 |
Structure::buf2val(void **)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return sizeof(Structure);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
Structure::var(const string &name, bool exact_match, btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string n = www2id(name);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (exact_match)
|
|
Packit |
a4aae4 |
return m_exact_match(n, s);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return m_leaf_match(n, s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @deprecated See comment in BaseType */
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
Structure::var(const string &n, btp_stack &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string name = www2id(n);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *btp = m_exact_match(name, &s);
|
|
Packit |
a4aae4 |
if (btp)
|
|
Packit |
a4aae4 |
return btp;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return m_leaf_match(name, &s);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// Private method to find a variable using the shorthand name. This
|
|
Packit |
a4aae4 |
// should be moved to Constructor.
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
Structure::m_leaf_match(const string &name, btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->name() == name) {
|
|
Packit |
a4aae4 |
if (s) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Pushing " << this->name() << endl);
|
|
Packit |
a4aae4 |
s->push(static_cast<BaseType *>(this));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return *i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if ((*i)->is_constructor_type()) {
|
|
Packit |
a4aae4 |
BaseType *btp = (*i)->var(name, false, s);
|
|
Packit |
a4aae4 |
if (btp) {
|
|
Packit |
a4aae4 |
if (s) {
|
|
Packit |
a4aae4 |
DBG(cerr << "Pushing " << this->name() << endl);
|
|
Packit |
a4aae4 |
s->push(static_cast<BaseType *>(this));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return btp;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Breadth-first search for NAME. If NAME contains one or more dots (.)
|
|
Packit |
a4aae4 |
// TODO The btp_stack is not needed since there are 'back pointers' in
|
|
Packit |
a4aae4 |
// BaseType.
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
Structure::m_exact_match(const string &name, btp_stack *s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Look for name at the top level first.
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
if ((*i)->name() == name) {
|
|
Packit |
a4aae4 |
if (s)
|
|
Packit |
a4aae4 |
s->push(static_cast<BaseType *>(this));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return *i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If it was not found using the simple search, look for a dot and
|
|
Packit |
a4aae4 |
// search the hierarchy.
|
|
Packit |
a4aae4 |
string::size_type dot_pos = name.find("."); // zero-based index of `.'
|
|
Packit |
a4aae4 |
if (dot_pos != string::npos) {
|
|
Packit |
a4aae4 |
string aggregate = name.substr(0, dot_pos);
|
|
Packit |
a4aae4 |
string field = name.substr(dot_pos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
BaseType *agg_ptr = var(aggregate);
|
|
Packit |
a4aae4 |
if (agg_ptr) {
|
|
Packit |
a4aae4 |
if (s)
|
|
Packit |
a4aae4 |
s->push(static_cast<BaseType *>(this));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return agg_ptr->var(field, true, s); // recurse
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return 0; // qualified names must be *fully* qualified
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::print_val(FILE *out, string space, bool print_decl_p)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print_val(oss, space, print_decl_p);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::print_val(ostream &out, string space, bool print_decl_p)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (print_decl_p) {
|
|
Packit |
a4aae4 |
print_decl(out, space, false);
|
|
Packit |
a4aae4 |
out << " = " ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << "{ " ;
|
|
Packit |
a4aae4 |
for (Vars_citer i = d_vars.begin(); i != d_vars.end();
|
|
Packit |
a4aae4 |
i++, (void)(i != d_vars.end() && out << ", ")) {
|
|
Packit |
a4aae4 |
(*i)->print_val(out, "", false);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << " }" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (print_decl_p)
|
|
Packit |
a4aae4 |
out << ";\n" ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
Structure::check_semantics(string &msg, bool all)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!BaseType::check_semantics(msg))
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool status = true;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!unique_names(d_vars, name(), type_name(), msg))
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (all) {
|
|
Packit |
a4aae4 |
for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
|
|
Packit |
a4aae4 |
//assert(*i);
|
|
Packit |
a4aae4 |
if (!(*i)->check_semantics(msg, true)) {
|
|
Packit |
a4aae4 |
status = false;
|
|
Packit |
a4aae4 |
goto exit;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
exit:
|
|
Packit |
a4aae4 |
return status;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief dumps information about this object
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Displays the pointer value of this instance and information about this
|
|
Packit |
a4aae4 |
* instance.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param strm C++ i/o stream to dump the information to
|
|
Packit |
a4aae4 |
* @return void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
Structure::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "Structure::dump - ("
|
|
Packit |
a4aae4 |
<< (void *)this << ")" << endl ;
|
|
Packit |
a4aae4 |
DapIndent::Indent() ;
|
|
Packit |
a4aae4 |
Constructor::dump(strm) ;
|
|
Packit |
a4aae4 |
DapIndent::UnIndent() ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|