Blame BaseType.cc

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 BaseType.
Packit a4aae4
//
Packit a4aae4
// jhrg 9/6/94
Packit a4aae4
Packit a4aae4
#include "config.h"
Packit a4aae4
Packit a4aae4
#include <cstdio>  // for stdin and stdout
Packit a4aae4
Packit a4aae4
#include <sstream>
Packit a4aae4
#include <string>
Packit a4aae4
Packit a4aae4
//#define DODS_DEBUG
Packit a4aae4
Packit a4aae4
#include "BaseType.h"
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 "D4Attributes.h"
Packit a4aae4
#include "DMR.h"
Packit a4aae4
#include "XMLWriter.h"
Packit a4aae4
#include "D4BaseTypeFactory.h"
Packit a4aae4
Packit a4aae4
#include "InternalErr.h"
Packit a4aae4
Packit a4aae4
#include "util.h"
Packit a4aae4
#include "escaping.h"
Packit a4aae4
Packit a4aae4
#include "debug.h"
Packit a4aae4
Packit a4aae4
using namespace std;
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
// Protected copy mfunc
Packit a4aae4
Packit a4aae4
/** Perform a deep copy. Copies the values of \e bt into \c *this. Pointers
Packit a4aae4
    are dereferenced and their values are copied into a newly allocated
Packit a4aae4
    instance.
Packit a4aae4
Packit a4aae4
    @brief Perform a deep copy.
Packit a4aae4
    @param bt The source object. */
Packit a4aae4
void
Packit a4aae4
BaseType::m_duplicate(const BaseType &bt)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "In BaseType::m_duplicate for " << bt.name() << endl);
Packit a4aae4
Packit a4aae4
    d_name = bt.d_name;
Packit a4aae4
    d_type = bt.d_type;
Packit a4aae4
    d_dataset = bt.d_dataset;
Packit a4aae4
    d_is_read = bt.d_is_read; // added, reza
Packit a4aae4
    d_is_send = bt.d_is_send; // added, reza
Packit a4aae4
    d_in_selection = bt.d_in_selection;
Packit a4aae4
    d_is_synthesized = bt.d_is_synthesized; // 5/11/2001 jhrg
Packit a4aae4
Packit a4aae4
    d_parent = bt.d_parent; // copy pointers 6/4/2001 jhrg
Packit a4aae4
Packit a4aae4
    d_attr = bt.d_attr;  // Deep copy.
Packit a4aae4
Packit a4aae4
    if (bt.d_attributes)
Packit a4aae4
        d_attributes = new D4Attributes(*bt.d_attributes); // deep copy
Packit a4aae4
    else
Packit a4aae4
        d_attributes = 0; // init to null if not used.
Packit a4aae4
Packit a4aae4
    d_is_dap4 = bt.d_is_dap4;
Packit a4aae4
Packit a4aae4
    DBG(cerr << "Exiting BaseType::m_duplicate for " << bt.name() << endl);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Public mfuncs
Packit a4aae4
Packit a4aae4
/** The BaseType constructor needs a name  and a type.
Packit a4aae4
    The BaseType class exists to provide data to
Packit a4aae4
    type classes that inherit from it.  The constructors of those
Packit a4aae4
    classes call the BaseType constructor; it is never called
Packit a4aae4
    directly.
Packit a4aae4
Packit a4aae4
    @brief The BaseType constructor.
Packit a4aae4
Packit a4aae4
    @param n A string containing the name of the new variable.
Packit a4aae4
    @param t The type of the variable.
Packit a4aae4
    @param is_dap4 True if this is a DAP4 variable. Default is False
Packit a4aae4
    @see Type */
Packit a4aae4
BaseType::BaseType(const string &n, const Type &t, bool is_dap4)
Packit a4aae4
: d_name(n), d_type(t), d_dataset(""), d_is_read(false), d_is_send(false),
Packit a4aae4
  d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
Packit a4aae4
  d_in_selection(false), d_is_synthesized(false)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
/** The BaseType constructor needs a name, a dataset, and a type.
Packit a4aae4
    The BaseType class exists to provide data to
Packit a4aae4
    type classes that inherit from it.  The constructors of those
Packit a4aae4
    classes call the BaseType constructor; it is never called
Packit a4aae4
    directly.
Packit a4aae4
Packit a4aae4
    @brief The BaseType constructor.
Packit a4aae4
    @param n A string containing the name of the new variable.
Packit a4aae4
    @param d A string containing the dataset name.
Packit a4aae4
    @param t The type of the variable. Default is False
Packit a4aae4
    @param is_dap4 True if this is a DAP4 variable.
Packit a4aae4
    @see Type */
Packit a4aae4
BaseType::BaseType(const string &n, const string &d, const Type &t, bool is_dap4)
Packit a4aae4
: d_name(n), d_type(t), d_dataset(d), d_is_read(false), d_is_send(false),
Packit a4aae4
  d_parent(0), d_attributes(0), d_is_dap4(is_dap4),
Packit a4aae4
  d_in_selection(false), d_is_synthesized(false)
Packit a4aae4
{}
Packit a4aae4
Packit a4aae4
/** @brief The BaseType copy constructor. */
Packit a4aae4
BaseType::BaseType(const BaseType &copy_from) : DapObj()
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "In BaseTpe::copy_ctor for " << copy_from.name() << endl);
Packit a4aae4
    m_duplicate(copy_from);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
BaseType::~BaseType()
Packit a4aae4
{
Packit a4aae4
    DBG2(cerr << "Entering ~BaseType (" << this << ")" << endl);
Packit a4aae4
Packit a4aae4
    if (d_attributes)
Packit a4aae4
        delete d_attributes;
Packit a4aae4
Packit a4aae4
    DBG2(cerr << "Exiting ~BaseType" << endl);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
BaseType &
Packit a4aae4
BaseType::operator=(const BaseType &rhs)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Entering BaseType::operator=" << endl);
Packit a4aae4
    if (this == &rhs)
Packit a4aae4
        return *this;
Packit a4aae4
Packit a4aae4
    m_duplicate(rhs);
Packit a4aae4
Packit a4aae4
    DBG(cerr << "Exiting BaseType::operator=" << endl);
Packit a4aae4
    return *this;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Write out the object's internal fields in a string. To be used for
Packit a4aae4
    debugging when regular inspection w/ddd or gdb isn't enough.
Packit a4aae4
Packit a4aae4
    @return A string which shows the object's internal stuff. */
Packit a4aae4
string BaseType::toString()
Packit a4aae4
{
Packit a4aae4
    ostringstream oss;
Packit a4aae4
    oss << "BaseType (" << this << "):" << endl
Packit a4aae4
        << "          _name: " << name() << endl
Packit a4aae4
        << "          _type: " << type_name() << endl
Packit a4aae4
        << "          _dataset: " << d_dataset << endl
Packit a4aae4
        << "          _read_p: " << d_is_read << endl
Packit a4aae4
        << "          _send_p: " << d_is_send << endl
Packit a4aae4
        << "          _synthesized_p: " << d_is_synthesized << endl
Packit a4aae4
        << "          d_parent: " << d_parent << endl
Packit a4aae4
        << "          d_attr: " << hex << &d_attr << dec << endl;
Packit a4aae4
Packit a4aae4
    return oss.str();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief DAP2 to DAP4 transform
Packit a4aae4
 *
Packit a4aae4
 * For the current BaseType, return a DAP4 'copy' of the variable.
Packit a4aae4
 *
Packit a4aae4
 * @note For most DAP2 types, in this implementation of DAP4 the corresponding
Packit a4aae4
 * DAP4 type is the same. The different types are Sequences (which are D4Sequences
Packit a4aae4
 * in the DAP4 implementation), Grids (which are coverages) and Arrays (which use
Packit a4aae4
 * shared dimensions).
Packit a4aae4
 *
Packit a4aae4
 * @param root The root group that should hold this new variable. Add Group-level
Packit a4aae4
 * stuff here (e.g., D4Dimensions).
Packit a4aae4
 * @param container Add the new variable to this container.
Packit a4aae4
 *
Packit a4aae4
 * @return A pointer to the transformed variable
Packit a4aae4
 */
Packit a4aae4
void
Packit a4aae4
BaseType::transform_to_dap4(D4Group */*root*/, Constructor *container)
Packit a4aae4
{
Packit a4aae4
    BaseType *dest = ptr_duplicate();
Packit a4aae4
    // If it's already a DAP4 object then we can just return it!
Packit a4aae4
    if(!is_dap4()){
Packit a4aae4
        dest->attributes()->transform_to_dap4(get_attr_table());
Packit a4aae4
        dest->set_is_dap4(true);
Packit a4aae4
    }
Packit a4aae4
    container->add_var_nocopy(dest);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** @brief DAP4 to DAP2 transform
Packit a4aae4
 *
Packit a4aae4
 * For the current BaseType, return a DAP2 'copy' of the variable.
Packit a4aae4
 *
Packit a4aae4
 * @note For most DAP4 types, in this implementation of DAP2 the corresponding
Packit a4aae4
 * DAP4 type is the same.
Packit a4aae4
 * These types have a different representations in DAP2 and DAP4:
Packit a4aae4
 *  Sequences (which are D4Sequences in the DAP4 implementation),
Packit a4aae4
 *  - Grids (which are semantically subsumed by coverages in DAP4)
Packit a4aae4
 *  - Arrays (which use shared dimensions in DAP4)
Packit a4aae4
 *
Packit a4aae4
 *  Additionally DAP4 adds the following types:
Packit a4aae4
 *  - UInt8, Int8, and Char which map to Byte in DAP2.
Packit a4aae4
 *  - Int64, Unit64 which have no natural representation in DAP2.
Packit a4aae4
 *  - Opaque Possible Byte stuff[] plus metadata?
Packit a4aae4
 *  - Enum's can be represented as Int32.
Packit a4aae4
 *
Packit a4aae4
 *  - Groups, with the exception of the root group "disappear" into the
Packit a4aae4
 *    names of their member variables. Specifically the Group name is add as a prefix
Packit a4aae4
 *    followed by a "/" separator to the names of all of the Group's member groups
Packit a4aae4
 *    variables.
Packit a4aae4
 *
Packit a4aae4
 * @param  The AttrTable pointer parent_attr_table is used by Groups, which disappear
Packit a4aae4
 * from the DAP2 representation. Their children are returned in the the BAseType vector
Packit a4aae4
 * their attributes are added to parent_attr_table;
Packit a4aae4
 * @return A pointer to a vector of BaseType pointers (right?). In most cases this vector
Packit a4aae4
 * will contain a single pointer but DAP4 types 'disappear' such as Group will return all
Packit a4aae4
 * of their member variables in the vector. DAP4 types with no representation in DAP2
Packit a4aae4
 * (ex: UInt64) the will return a NULL pointer and so this must be tested!
Packit a4aae4
 */
Packit a4aae4
std::vector<BaseType *> *
Packit a4aae4
BaseType::transform_to_dap2(AttrTable *)
Packit a4aae4
{
Packit a4aae4
    BaseType *dest = this->ptr_duplicate();
Packit a4aae4
    // convert the d4 attributes to a dap2 attribute table.
Packit a4aae4
    AttrTable *attrs = this->attributes()->get_AttrTable(name());
Packit a4aae4
    dest->set_attr_table(*attrs);
Packit a4aae4
    dest->set_is_dap4(false);
Packit a4aae4
    // attrs->print(cerr,"",true);
Packit a4aae4
Packit a4aae4
    vector<BaseType *> *result =  new vector<BaseType *>();
Packit a4aae4
    result->push_back(dest);
Packit a4aae4
    return result;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** @brief dumps information about this object
Packit a4aae4
 *
Packit a4aae4
 * Displays the pointer value of this instance and then displays information
Packit a4aae4
 * about this base type.
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
BaseType::dump(ostream &strm) const
Packit a4aae4
{
Packit a4aae4
    strm << DapIndent::LMarg << "BaseType::dump - ("
Packit a4aae4
        << (void *)this << ")" << endl ;
Packit a4aae4
    DapIndent::Indent() ;
Packit a4aae4
Packit a4aae4
    strm << DapIndent::LMarg << "name: " << name() << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "type: " << type_name() << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "dataset: " << d_dataset << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "read_p: " << d_is_read << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "send_p: " << d_is_send << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "synthesized_p: " << d_is_synthesized << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "parent: " << (void *)d_parent << endl ;
Packit a4aae4
    strm << DapIndent::LMarg << "attributes: " << endl ;
Packit a4aae4
    DapIndent::Indent() ;
Packit a4aae4
Packit a4aae4
    if (d_attributes)
Packit a4aae4
        d_attributes->dump(strm);
Packit a4aae4
    else
Packit a4aae4
        d_attr.dump(strm) ;
Packit a4aae4
Packit a4aae4
    DapIndent::UnIndent() ;
Packit a4aae4
Packit a4aae4
    DapIndent::UnIndent() ;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns the name of the class instance.
Packit a4aae4
 */
Packit a4aae4
string
Packit a4aae4
BaseType::name() const
Packit a4aae4
{
Packit a4aae4
    return d_name;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Return the FQN for this variable. This will include the D4 Group
Packit a4aae4
 * component of the name.
Packit a4aae4
 *
Packit a4aae4
 * @return The FQN in a string
Packit a4aae4
 */
Packit a4aae4
string
Packit a4aae4
BaseType::FQN() const
Packit a4aae4
{
Packit a4aae4
    if (get_parent() == 0)
Packit a4aae4
        return name();
Packit a4aae4
    else if (get_parent()->type() == dods_group_c)
Packit a4aae4
        return get_parent()->FQN() + name();
Packit a4aae4
    else
Packit a4aae4
        return get_parent()->FQN() + "." + name();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Sets the name of the class instance. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_name(const string &n)
Packit a4aae4
{
Packit a4aae4
    string name = n;
Packit a4aae4
    d_name = www2id(name); // www2id writes into its param.
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns the name of the dataset used to create this instance
Packit a4aae4
Packit a4aae4
    A dataset from which the data is to be read. The meaning of this string
Packit a4aae4
    will vary among different types of data sources. It \e may be the name
Packit a4aae4
    of a data file or an identifier used to read data from a relational
Packit a4aae4
    database.
Packit a4aae4
 */
Packit a4aae4
string
Packit a4aae4
BaseType::dataset() const
Packit a4aae4
{
Packit a4aae4
    return d_dataset;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns the type of the class instance. */
Packit a4aae4
Type
Packit a4aae4
BaseType::type() const
Packit a4aae4
{
Packit a4aae4
    return d_type;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Sets the type of the class instance. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_type(const Type &t)
Packit a4aae4
{
Packit a4aae4
    d_type = t;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns the type of the class instance as a string. */
Packit a4aae4
string
Packit a4aae4
BaseType::type_name() const
Packit a4aae4
{
Packit a4aae4
    if (is_dap4())
Packit a4aae4
        return libdap::D4type_name(d_type);
Packit a4aae4
    else
Packit a4aae4
        return libdap::D2type_name(d_type);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns true if the instance is a numeric, string or URL
Packit a4aae4
    type variable.
Packit a4aae4
    @return True if the instance is a scalar numeric, String or URL variable,
Packit a4aae4
    False otherwise. Arrays (even of simple types) return False.
Packit a4aae4
    @see is_vector_type() */
Packit a4aae4
bool
Packit a4aae4
BaseType::is_simple_type() const
Packit a4aae4
{
Packit a4aae4
    return libdap::is_simple_type(type());
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns true if the instance is a vector (i.e., array) type
Packit a4aae4
    variable.
Packit a4aae4
    @return True if the instance is an Array, False otherwise. */
Packit a4aae4
bool
Packit a4aae4
BaseType::is_vector_type() const
Packit a4aae4
{
Packit a4aae4
    return libdap::is_vector_type(type());
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Returns true if the instance is a constructor (i.e., Structure,
Packit a4aae4
    Sequence or Grid) type variable.
Packit a4aae4
    @return True if the instance is a Structure, Sequence or Grid, False
Packit a4aae4
    otherwise. */
Packit a4aae4
bool
Packit a4aae4
BaseType::is_constructor_type() const
Packit a4aae4
{
Packit a4aae4
    return libdap::is_constructor_type(type());
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Return a count of the total number of variables in this variable.
Packit a4aae4
    This is used to count the number of variables held by a constructor
Packit a4aae4
    variable - for simple type and vector variables it always
Packit a4aae4
    returns 1.
Packit a4aae4
Packit a4aae4
    For compound data types, there are two ways to count members.
Packit a4aae4
    You can count the members, or you can count the simple members
Packit a4aae4
    and add that to the count of the compound members.  For
Packit a4aae4
    example, if a Structure contains an Int32 and another
Packit a4aae4
    Structure that itself contains two Int32 members, the element
Packit a4aae4
    count of the top-level structure could be two (one Int32 and
Packit a4aae4
    one Structure) or three (one Int32 by itself and two Int32's
Packit a4aae4
    in the subsidiary Structure).  Use the leaves parameter
Packit a4aae4
    to control which kind of counting you desire.
Packit a4aae4
Packit a4aae4
    @brief Count the members of constructor types.
Packit a4aae4
    @return Returns 1 for simple
Packit a4aae4
    types.  For compound members, the count depends on the
Packit a4aae4
    leaves argument.
Packit a4aae4
    @param leaves This parameter is only relevant if the object
Packit a4aae4
    contains other compound data types.  If FALSE, the function
Packit a4aae4
    counts only the data variables mentioned in the object's
Packit a4aae4
    declaration.  If TRUE, it counts the simple members, and adds
Packit a4aae4
    that to the sum of the counts for the compound members.
Packit a4aae4
    This parameter has no effect for simple type variables. */
Packit a4aae4
int
Packit a4aae4
BaseType::element_count(bool)
Packit a4aae4
{
Packit a4aae4
    return 1;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns true if the variable is a synthesized variable. A synthesized
Packit a4aae4
    variable is one that is added to the dataset by the server (usually
Packit a4aae4
    with a `projection function'. */
Packit a4aae4
bool
Packit a4aae4
BaseType::synthesized_p()
Packit a4aae4
{
Packit a4aae4
    return d_is_synthesized;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Set the synthesized flag. Before setting this flag be sure to set the
Packit a4aae4
    <tt>read_p()</tt> state. Once this flag is set you cannot
Packit a4aae4
    alter the state of the <tt>read_p</tt> flag!
Packit a4aae4
Packit a4aae4
    @see synthesized_p() */
Packit a4aae4
void
Packit a4aae4
BaseType::set_synthesized_p(bool state)
Packit a4aae4
{
Packit a4aae4
    d_is_synthesized = state;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Return the state of d_is_read (true if the value of the variable has been
Packit a4aae4
// read (and is in memory) false otherwise).
Packit a4aae4
Packit a4aae4
/** Returns true if the value(s) for this variable have been read from the
Packit a4aae4
    data source, otherwise returns false. This method is used to determine
Packit a4aae4
    when values need to be read using the read() method. When read_p()
Packit a4aae4
    returns true, this library assumes that buf2val() (and other methods
Packit a4aae4
    such as get_vec()) can be used to access the value(s) of a variable.
Packit a4aae4
Packit a4aae4
    @brief Has this variable been read?
Packit a4aae4
    @return True if the variable's value(s) have been read, false otherwise. */
Packit a4aae4
bool
Packit a4aae4
BaseType::read_p()
Packit a4aae4
{
Packit a4aae4
    return d_is_read;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Sets the value of the <tt>read_p</tt> property. This indicates that the
Packit a4aae4
    value(s) of this variable has/have been read. An implementation of the
Packit a4aae4
    read() method should use this to set the \c read_p property to true.
Packit a4aae4
Packit a4aae4
    @note If the is_synthesized property is true, this method will _not_
Packit a4aae4
    alter the is_read property. If you need that behavior, specialize the
Packit a4aae4
    method in your subclasses if the various types.
Packit a4aae4
Packit a4aae4
    @note For most of the types the default implementation of this method is
Packit a4aae4
    fine. However, if you're building a server which must handle data
Packit a4aae4
    represented using nested sequences, then you may need to provide a
Packit a4aae4
    specialization of Sequence::set_read_p(). By default Sequence::set_read_p()
Packit a4aae4
    recursively sets the \e read_p property for all child variables to
Packit a4aae4
    \e state. For servers where one Sequence reads an outer set of values
Packit a4aae4
    and another reads an inner set, this is cumbersome. In such a case, it is
Packit a4aae4
    easier to specialize Sequence::set_read_p() so that it does \e not
Packit a4aae4
    recursively set the \e read_p property for the inner Sequence. Be sure
Packit a4aae4
    to see the documentation for the read() method!
Packit a4aae4
Packit a4aae4
    @todo Look at making synthesized variables easier to implement and at
Packit a4aae4
    making them more integrated into the overall CE evaluation process.
Packit a4aae4
    Maybe the code that computes the synthesized var's value should be in the
Packit a4aae4
    that variable's read() method? This might provide a way to get rid of the
Packit a4aae4
    awkward 'projection functions' by replacing them with real children of
Packit a4aae4
    BaseType. It would also provide a way to clean up the way the
Packit a4aae4
    \e synthesized_p prop intrudes on the \e read_p prop.
Packit a4aae4
Packit a4aae4
    @see BaseType::read()
Packit a4aae4
    @brief Sets the value of the \e read_p property.
Packit a4aae4
    @param state Set the \e read_p property to this state. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_read_p(bool state)
Packit a4aae4
{
Packit a4aae4
    // The this comment is/was wrong!
Packit a4aae4
    // The is_synthesized property was not being used and the more I thought
Packit a4aae4
    // about how this was coded, the more this code below seemed like a bad idea.
Packit a4aae4
    // Once the property was set, the read_p property could not be changed.
Packit a4aae4
    // That seems a little silly. Also, I think I need to use this is_synthesized
Packit a4aae4
    // property for some of the server function code I'm working on for Raytheon,
Packit a4aae4
    // and I'd like to be able to control the read_p property! jhrg 3/9/15
Packit a4aae4
Packit a4aae4
    // What's true: The is_synthesized property is used by
Packit a4aae4
    // 'projection functions' in the freeform handler. It might be better
Packit a4aae4
    // to modify the FFtypes to support this behavior, but for now I'm returning
Packit a4aae4
    // the library to its old behavior. That this change (setting is_read
Packit a4aae4
    // of the value of is_syn...) broke the FF handler was not detected
Packit a4aae4
    // because the FF tests were not being run due to an error in the FF
Packit a4aae4
    // bes-testsuite Makefile.am). jhrg 9/9/15
Packit a4aae4
Packit a4aae4
#if 1
Packit a4aae4
    if (!d_is_synthesized) {
Packit a4aae4
        d_is_read = state;
Packit a4aae4
    }
Packit a4aae4
#else
Packit a4aae4
    d_is_read = state;
Packit a4aae4
#endif
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns the state of the \c send_p property. If true, this variable
Packit a4aae4
    should be sent to the client, if false, it should not. If no constraint
Packit a4aae4
    expression (CE) has been evaluated, this property is true for all
Packit a4aae4
    variables in a data source (i.e., for all the variables listed in a DDS).
Packit a4aae4
    If a CE has been evaluated, this property is true only for those
Packit a4aae4
    variables listed in the projection part of the CE.
Packit a4aae4
Packit a4aae4
    @brief Should this variable be sent?
Packit a4aae4
    @return True if the variable should be sent to the client, false
Packit a4aae4
    otherwise. */
Packit a4aae4
bool
Packit a4aae4
BaseType::send_p()
Packit a4aae4
{
Packit a4aae4
    return d_is_send;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Sets the value of the <tt>send_p</tt> flag.  This
Packit a4aae4
    function is meant to be called from within the constraint evaluator of
Packit a4aae4
    other code which determines that this variable should be returned to the
Packit a4aae4
    client.  Data are ready to be sent when both the <tt>d_is_send</tt>
Packit a4aae4
    and <tt>d_is_read</tt> flags are set to TRUE.
Packit a4aae4
Packit a4aae4
    @param state The logical state to set the <tt>send_p</tt> flag.
Packit a4aae4
 */
Packit a4aae4
void
Packit a4aae4
BaseType::set_send_p(bool state)
Packit a4aae4
{
Packit a4aae4
    DBG2(cerr << "Calling BaseType::set_send_p() for: " << this->name()
Packit a4aae4
        << endl);
Packit a4aae4
    d_is_send = state;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** Get this variable's AttrTable. It's generally a bad idea to return a
Packit a4aae4
    reference to a contained object, but in this case it seems that building
Packit a4aae4
    an interface inside BaseType is overkill.
Packit a4aae4
Packit a4aae4
    Use the AttrTable methods to manipulate the table. */
Packit a4aae4
AttrTable &
Packit a4aae4
BaseType::get_attr_table()
Packit a4aae4
{
Packit a4aae4
    return d_attr;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Set this variable's attribute table.
Packit a4aae4
    @param at Source of the attributes. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_attr_table(const AttrTable &at)
Packit a4aae4
{
Packit a4aae4
    d_attr = at;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** DAP4 Attribute methods
Packit a4aae4
 * @{
Packit a4aae4
 */
Packit a4aae4
D4Attributes *
Packit a4aae4
BaseType::attributes()
Packit a4aae4
{
Packit a4aae4
    if (!d_attributes) d_attributes = new D4Attributes();
Packit a4aae4
    return d_attributes;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
BaseType::set_attributes(D4Attributes *attrs)
Packit a4aae4
{
Packit a4aae4
    d_attributes = new D4Attributes(*attrs);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
BaseType::set_attributes_nocopy(D4Attributes *attrs)
Packit a4aae4
{
Packit a4aae4
    d_attributes = attrs;
Packit a4aae4
}
Packit a4aae4
///@}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Transfer attributes from a DAS object into this variable. Because of the
Packit a4aae4
 * rough history of the DAS object and the way that various server code built
Packit a4aae4
 * the DAS, this is necessarily a heuristic process. The intent is that this
Packit a4aae4
 * method will be overridden by handlers that need to look for certain patterns
Packit a4aae4
 * in the DAS (e.g., hdf4's odd variable_dim_n; where n = 0, 1, 2, ...)
Packit a4aae4
 * attribute containers.
Packit a4aae4
 *
Packit a4aae4
 * There should be a one-to-one
Packit a4aae4
 * mapping between variables and attribute containers. However, in some cases
Packit a4aae4
 * one variable has attributes spread across several top level containers and
Packit a4aae4
 * in some cases one container is used by several variables
Packit a4aae4
 *
Packit a4aae4
 * @note This method is technically \e unnecessary because a server (or
Packit a4aae4
 * client) can easily add attributes directly using the DDS::get_attr_table
Packit a4aae4
 * or BaseType::get_attr_table methods and then poke values in using any
Packit a4aae4
 * of the methods AttrTable provides. This method exists to ease the
Packit a4aae4
 * transition to DDS objects which contain attribute information for the
Packit a4aae4
 * existing servers (Since they all make DAS objects separately from the
Packit a4aae4
 * DDS). They could be modified to use the same AttrTable methods but
Packit a4aae4
 * operate on the AttrTable instances in a DDS/BaseType instead of those in
Packit a4aae4
 * a DAS.
Packit a4aae4
 *
Packit a4aae4
 * @param at_container Transfer attributes from this container.
Packit a4aae4
 * @return void
Packit a4aae4
 */
Packit a4aae4
void BaseType::transfer_attributes(AttrTable *at_container) {
Packit a4aae4
Packit a4aae4
    DBG(cerr << __func__ << "() -  BEGIN name:'" << name() << "'" << endl);
Packit a4aae4
Packit a4aae4
    AttrTable *at = at_container->get_attr_table(name());
Packit a4aae4
    DBG(cerr << __func__ << "() - at: "<< (void *) at << endl);
Packit a4aae4
Packit a4aae4
Packit a4aae4
    if (at) {
Packit a4aae4
        at->set_is_global_attribute(false);
Packit a4aae4
        DBG(cerr << __func__ << "() - Processing AttrTable: " << at->get_name() << endl);
Packit a4aae4
Packit a4aae4
        AttrTable::Attr_iter at_p = at->attr_begin();
Packit a4aae4
        while (at_p != at->attr_end()) {
Packit a4aae4
            DBG(cerr << __func__ << "() -  Attribute '" << at->get_name(at_p) << "' is type: " << at->get_type(at_p) << endl);
Packit a4aae4
            if (at->get_attr_type(at_p) == Attr_container){
Packit a4aae4
                // An attribute container may actually represent a child member variable. When
Packit a4aae4
                // that's the case we don't want to add the container to the parent type, but
Packit a4aae4
                // rather let any child of BaseType deal with those containers in the child's
Packit a4aae4
                // overridden transfer_attributes() method.
Packit a4aae4
                // We capitalize on the magic of the BaseType API and utilize the var() method
Packit a4aae4
                // to check for a child variable of the same name and, if one exists, we'll skip
Packit a4aae4
                // this AttrTable and let a child constructor class like Grid or Constructor
Packit a4aae4
                // deal with it.
Packit a4aae4
                BaseType *bt = var(at->get_name(at_p),true);
Packit a4aae4
                if(bt==0){
Packit a4aae4
                    DBG(cerr << __func__ << "() - Adding container '" << at->get_name(at_p) << endl);
Packit a4aae4
                    get_attr_table().append_container(new AttrTable(*at->get_attr_table(at_p)), at->get_name(at_p));
Packit a4aae4
                }
Packit a4aae4
                else {
Packit a4aae4
                    DBG(cerr << __func__ << "() - Found child var: '"<< bt->type_name()<< " " << bt->name() << " (address:" << (void *) bt << ")" << endl);
Packit a4aae4
                    DBG(cerr << __func__ << "() -  Skipping container '" << at->get_name(at_p) << endl);
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
            else {
Packit a4aae4
                DBG(cerr << __func__ << "() - Adding Attribute '" << at->get_name(at_p) << endl);
Packit a4aae4
                get_attr_table().append_attr(at->get_name(at_p), at->get_type(at_p), at->get_attr_vector(at_p));
Packit a4aae4
            }
Packit a4aae4
            at_p++;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        DBG(cerr << __func__ << "() - Unable to locate AttrTable '" << name() << "'  SKIPPING" << endl);
Packit a4aae4
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Does this variable appear in either the selection part or as a function
Packit a4aae4
    argument in the current constrain expression. If this property is set
Packit a4aae4
    (true) then implementations of the read() method should read this
Packit a4aae4
    variable.
Packit a4aae4
Packit a4aae4
    @note This method does not check, nor does it know about the semantics of,
Packit a4aae4
    string arguments passed to functions. Those functions might include
Packit a4aae4
    variable names in strings; they are responsible for reading those variables.
Packit a4aae4
    See the grid (func_grid_select()) for an example.
Packit a4aae4
    @see BaseType::read()
Packit a4aae4
    @brief Is this variable part of the current selection? */
Packit a4aae4
bool
Packit a4aae4
BaseType::is_in_selection()
Packit a4aae4
{
Packit a4aae4
    return d_in_selection;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Set the \e in_selection property to \e state. This property indicates
Packit a4aae4
    that the variable is used as a parameter to a constraint expression
Packit a4aae4
    function or that it appears as an argument in a selection sub-expression.
Packit a4aae4
    If set (true), implementations of the BaseType::read() method should read
Packit a4aae4
    this variable.
Packit a4aae4
Packit a4aae4
    @param state Set the \e in_selection property to this state.
Packit a4aae4
    @see BaseType::read()
Packit a4aae4
    @see BaseType::is_in_selection() for more information. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_in_selection(bool state)
Packit a4aae4
{
Packit a4aae4
    d_in_selection = state;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Protected method.
Packit a4aae4
/** Set the <tt>parent</tt> property for this variable.
Packit a4aae4
Packit a4aae4
    @note Added ability to set parent to null. 10/19/12 jhrg
Packit a4aae4
Packit a4aae4
    @param parent Pointer to the Constructor of Vector parent variable or null
Packit a4aae4
    if the variable has no parent (if it is at the top-level of a DAP2/3 DDS).
Packit a4aae4
    @exception InternalErr thrown if called with anything other than a
Packit a4aae4
    Constructor, Vector or Null. */
Packit a4aae4
void
Packit a4aae4
BaseType::set_parent(BaseType *parent)
Packit a4aae4
{
Packit a4aae4
    if (!dynamic_cast<Constructor *>(parent)
Packit a4aae4
        && !dynamic_cast<Vector *>(parent)
Packit a4aae4
        && parent != 0)
Packit a4aae4
        throw InternalErr("Call to set_parent with incorrect variable type.");
Packit a4aae4
Packit a4aae4
    d_parent = parent;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Public method.
Packit a4aae4
Packit a4aae4
/** Return a pointer to the Constructor or Vector which holds (contains)
Packit a4aae4
    this variable. If this variable is at the top level, this method
Packit a4aae4
    returns null.
Packit a4aae4
Packit a4aae4
    @return A BaseType pointer to the variable's parent. */
Packit a4aae4
BaseType *
Packit a4aae4
BaseType::get_parent() const
Packit a4aae4
{
Packit a4aae4
    return d_parent;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Documented in the header file.
Packit a4aae4
BaseType *
Packit a4aae4
BaseType::var(const string &/*name*/, bool /*exact_match*/, btp_stack */*s*/)
Packit a4aae4
{
Packit a4aae4
    return static_cast<BaseType *>(0);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** This version of var(...) searches for name and returns a
Packit a4aae4
    pointer to the BaseType object if found. It uses the same search
Packit a4aae4
    algorithm as BaseType::var(const string &, bool, btp_stack *) when
Packit a4aae4
    exact_match is false. In addition to returning a pointer to
Packit a4aae4
    the variable, it pushes onto s a BaseType pointer to each
Packit a4aae4
    constructor type that ultimately contains name.
Packit a4aae4
Packit a4aae4
    @note The BaseType implementation always returns null. There are no default
Packit a4aae4
    values for the parameters. If var() is called w/o any params, the three
Packit a4aae4
    parameter version will be used.
Packit a4aae4
Packit a4aae4
    @deprecated This method is deprecated because it tries first to use
Packit a4aae4
    exact_match and, if that fails, then tries leaf_match. It's better to use
Packit a4aae4
    the alternate form of var(...) and specify exactly what you'd like to do.
Packit a4aae4
Packit a4aae4
    @return A pointer to the named variable. */
Packit a4aae4
BaseType *
Packit a4aae4
BaseType::var(const string &, btp_stack &)
Packit a4aae4
{
Packit a4aae4
    return static_cast<BaseType *>(0);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Adds a variable to an instance of a constructor class, such as Array,
Packit a4aae4
    Structure et cetera. This function is only used by those
Packit a4aae4
    classes. For constructors with more than one variable, the variables
Packit a4aae4
    appear in the same order in which they were added (i.e., the order in
Packit a4aae4
    which add_var() was called). Since this method is only for use by Vectors
Packit a4aae4
    and Constructors, the BaseType implementation throws InternalErr.
Packit a4aae4
Packit a4aae4
    @note For the implementation of this method in Structure, Sequence, et c.,
Packit a4aae4
    first copy \e bt and then insert the copy. If \e bt is itself a constructor
Packit a4aae4
    type you must either use the var() method to get a pointer to the actual
Packit a4aae4
    instance added to \c *this or you must first add all of bt's
Packit a4aae4
    children to it before adding it to \c *this. The implementations should use
Packit a4aae4
    m_duplicate() to perform a deep copy of \e bt.
Packit a4aae4
Packit a4aae4
    @brief Add a variable.
Packit a4aae4
Packit a4aae4
    @todo We should get rid of the Part parameter and adopt the convention
Packit a4aae4
    that the first variable is the Array and all subsequent ones are Maps
Packit a4aae4
    (when dealing with a Grid, the only time Part matters). This would enable
Packit a4aae4
    several methods to migrate from Structure, Sequence and Grid to
Packit a4aae4
    Constructor.
Packit a4aae4
Packit a4aae4
    @param bt The variable to be added to this instance. The caller of this
Packit a4aae4
    method must free memory it allocates for <tt>v</tt>. This method
Packit a4aae4
    will make a deep copy of the object pointed to by <tt>v</tt>.
Packit a4aae4
    @param part The part of the constructor data to be modified. Only
Packit a4aae4
    meaningful for Grid variables.
Packit a4aae4
Packit a4aae4
    @see Part */
Packit a4aae4
void
Packit a4aae4
BaseType::add_var(BaseType *, Part)
Packit a4aae4
{
Packit a4aae4
    throw InternalErr(__FILE__, __LINE__, "BaseType::add_var unimplemented");
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
BaseType::add_var_nocopy(BaseType *, Part)
Packit a4aae4
{
Packit a4aae4
    throw InternalErr(__FILE__, __LINE__, "BaseType::add_var_nocopy unimplemented");
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** This method should be implemented for each of the data type classes (Byte,
Packit a4aae4
    ..., Grid) when using the DAP class library to build a server. This
Packit a4aae4
    method is only for DAP servers. The library provides a default
Packit a4aae4
    definition here which throws an InternalErr exception \e unless the read_p
Packit a4aae4
    property has been set. In that case it returns false, indicating that all
Packit a4aae4
    the data have been read. The latter case can happen when building a
Packit a4aae4
    constant value that needs to be passed to a function. The variable/constant
Packit a4aae4
    is loaded with a value when it is created.
Packit a4aae4
Packit a4aae4
    When implementing a new DAP server, the Byte, ..., Grid data type classes
Packit a4aae4
    are usually specialized. In each of those specializations read() should
Packit a4aae4
    be defined to read values from the data source and store them in the
Packit a4aae4
    object's local buffer. The read() method is called by other methods in
Packit a4aae4
    this library. When writing read(), follow these rules:
Packit a4aae4
Packit a4aae4
    
    Packit a4aae4
        
  • read() should throw Error if it encounters an error. The message
  • Packit a4aae4
       should be verbose enough to be understood by someone running a
    Packit a4aae4
       client on a different machine.
    Packit a4aae4
        
  • The value(s) should be read if and only if either send_p() or
  • Packit a4aae4
              is_in_selection() return true. If neither of these return true, the
    Packit a4aae4
       value(s) should not be read. This is important when writing read()
    Packit a4aae4
       for a Constructor type such as Grid where a client may ask for only
    Packit a4aae4
       the map vectors (and thus reading the much larger Array part is not
    Packit a4aae4
       needed).
    Packit a4aae4
        
  • For each specialization of read(), the method should first test
  • Packit a4aae4
              the value of the \c read_p property (using the read_p() method)
    Packit a4aae4
              and read values only if the value of read_p() is false. Once the
    Packit a4aae4
              read() method reads data and stores it in the instance, it must
    Packit a4aae4
              set the value of the \c read_p property to true using set_read_p().
    Packit a4aae4
              If your read() methods fail to do this data may not serialize
    Packit a4aae4
              correctly.
    Packit a4aae4
        
  • The Array::read() and Grid::read() methods should take into account
  • Packit a4aae4
       any restrictions on Array sizes.
    Packit a4aae4
        
  • If you are writing Sequence::read(), be sure to check the
  • Packit a4aae4
              documentation for Sequence::read_row() and Sequence::serialize()
    Packit a4aae4
              so you understand how Sequence::read() is being called.
    Packit a4aae4
        
  • For Sequence::read(), your specialization must correctly manage the
  • Packit a4aae4
              \c unsent_data property and row count in addition to the \c read_p
    Packit a4aae4
              property (handle the \c read_p property as describe above). For a
    Packit a4aae4
              Sequence to serialize correctly, once all data from the Sequence
    Packit a4aae4
              has been read, \c unsent_data property must be set to false (use
    Packit a4aae4
              Sequence::set_unsent_data()). Also, at that time the row number
    Packit a4aae4
              counter must be reset (use Sequence::reset_row_counter()). Typically
    Packit a4aae4
              the correct time to set \c unsent_data to false and reset the row
    Packit a4aae4
              counter is the time when Sequence::read() return false indicating
    Packit a4aae4
              that all the data for the Sequence have been read. Failure to
    Packit a4aae4
              handle these tasks will break serialization of nested Sequences. Note
    Packit a4aae4
              that when Sequence::read() returns with a result of true (indicating
    Packit a4aae4
              there is more data to send, the value of the \c unsent_data property
    Packit a4aae4
              should be true.
    Packit a4aae4
    Packit a4aae4
              Also, if you server must handle nested sequences, be sure to read
    Packit a4aae4
              about subclassing set_read_p().
    Packit a4aae4
        
    Packit a4aae4
    Packit a4aae4
        @brief Read data into a local buffer.
    Packit a4aae4
    Packit a4aae4
    	@todo Modify the D4 serialize code so that it supports the true/false
    Packit a4aae4
    	behavior of read() for arrays.
    Packit a4aae4
    Packit a4aae4
    	@todo Modify all of the stock handlers so they conform to this!
    Packit a4aae4
    Packit a4aae4
        @return False means more data remains to be read, True indicates that no
    Packit a4aae4
        more data need to be read. For Sequence and D4Sequence, this method will
    Packit a4aae4
        generally read one instance of the Sequence; for other types it will generally
    Packit a4aae4
        read the entire variable modulo any limitations due to a constraint. However,
    Packit a4aae4
        the library should be written so that read can return less than all of the data
    Packit a4aae4
        for a variable - serialize() would then call the function until it returns
    Packit a4aae4
        True.
    Packit a4aae4
    Packit a4aae4
        @see BaseType */
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::read()
    Packit a4aae4
    {
    Packit a4aae4
        if (d_is_read)
    Packit a4aae4
            return true;
    Packit a4aae4
    Packit a4aae4
        throw InternalErr("Unimplemented BaseType::read() method called for the variable named: " + name());
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::intern_data(ConstraintEvaluator &, DDS &/*dds*/)
    Packit a4aae4
    {
    Packit a4aae4
    #if USE_LOCAL_TIMEOUT_SCHEME
    Packit a4aae4
        dds.timeout_on();
    Packit a4aae4
    #endif
    Packit a4aae4
        DBG2(cerr << "BaseType::intern_data: " << name() << endl);
    Packit a4aae4
        if (!read_p())
    Packit a4aae4
            read();          // read() throws Error and InternalErr
    Packit a4aae4
    #if USE_LOCAL_TIMEOUT_SCHEME
    Packit a4aae4
        dds.timeout_off();
    Packit a4aae4
    #endif
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /**
    Packit a4aae4
     * @brief Read data into this variable
    Packit a4aae4
     * @param eval Evaluator for a constraint expression
    Packit a4aae4
     * @param dmr DMR for the whole dataset
    Packit a4aae4
     */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::intern_data(/*Crc32 &checksum, DMR &, ConstraintEvaluator &*/)
    Packit a4aae4
    {
    Packit a4aae4
        if (!read_p())
    Packit a4aae4
            read();          // read() throws Error and InternalErr
    Packit a4aae4
    #if 0
    Packit a4aae4
        compute_checksum(checksum);
    Packit a4aae4
    #endif
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::serialize(ConstraintEvaluator &, DDS &,  Marshaller &, bool)
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The DAP2 serialize() method has not been implemented for " + type_name());
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::deserialize(UnMarshaller &, DDS *, bool)
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The DAP2 deserialize() method has not been implemented for " + type_name());
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::serialize(D4StreamMarshaller &, DMR &, /*ConstraintEvaluator &,*/ bool)
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The DAP4 serialize() method has not been implemented for " + type_name());
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::deserialize(D4StreamUnMarshaller &, DMR &)
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The DAP4 deserialize() method has not been implemented for " + type_name());
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Write the variable's declaration in a C-style syntax. This
    Packit a4aae4
        function is used to create textual representation of the Data
    Packit a4aae4
        Descriptor Structure (DDS).  See The DODS User Manual for
    Packit a4aae4
        information about this structure.
    Packit a4aae4
    Packit a4aae4
        A simple array declaration might look like this:
    Packit a4aae4
        \verbatim
    Packit a4aae4
        Float64 lat[lat = 180];
    Packit a4aae4
        \endverbatim
    Packit a4aae4
        While a more complex declaration (for a Grid, in this case),
    Packit a4aae4
        would look like this:
    Packit a4aae4
        \verbatim
    Packit a4aae4
        Grid {
    Packit a4aae4
        ARRAY:
    Packit a4aae4
        Int32 sst[time = 404][lat = 180][lon = 360];
    Packit a4aae4
        MAPS:
    Packit a4aae4
        Float64 time[time = 404];
    Packit a4aae4
        Float64 lat[lat = 180];
    Packit a4aae4
        Float64 lon[lon = 360];
    Packit a4aae4
        } sst;
    Packit a4aae4
        \endverbatim
    Packit a4aae4
    Packit a4aae4
        @brief Print an ASCII representation of the variable structure.
    Packit a4aae4
        @param out The output stream on which to print the
    Packit a4aae4
        declaration.
    Packit a4aae4
        @param space Each line of the declaration will begin with the
    Packit a4aae4
        characters in this string.  Usually used for leading spaces.
    Packit a4aae4
        @param print_semi A boolean value indicating whether to print a
    Packit a4aae4
        semicolon at the end of the declaration.
    Packit a4aae4
        @param constraint_info A boolean value indicating whether
    Packit a4aae4
        constraint information is to be printed with the declaration.
    Packit a4aae4
        If the value of this parameter is TRUE, <tt>print_decl()</tt> prints
    Packit a4aae4
        the value of the variable's <tt>send_p()</tt> flag after the
    Packit a4aae4
        declaration.
    Packit a4aae4
        @param constrained If this boolean value is TRUE, the variable's
    Packit a4aae4
        declaration is only printed if is the <tt>send_p()</tt> flag is TRUE.
    Packit a4aae4
        If a constraint expression is in place, and this variable is not
    Packit a4aae4
        requested, the <tt>send_p()</tt> flag is FALSE.
    Packit a4aae4
    Packit a4aae4
        @see DDS
    Packit a4aae4
        @see DDS::CE
    Packit a4aae4
     */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_decl(FILE *out, string space, bool print_semi,
    Packit a4aae4
        bool constraint_info, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        ostringstream oss;
    Packit a4aae4
        print_decl(oss, space, print_semi, constraint_info, constrained);
    Packit a4aae4
        fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Write the variable's declaration in a C-style syntax. This
    Packit a4aae4
        function is used to create textual representation of the Data
    Packit a4aae4
        Descriptor Structure (DDS).  See The DODS User Manual for
    Packit a4aae4
        information about this structure.
    Packit a4aae4
    Packit a4aae4
        A simple array declaration might look like this:
    Packit a4aae4
        \verbatim
    Packit a4aae4
        Float64 lat[lat = 180];
    Packit a4aae4
        \endverbatim
    Packit a4aae4
        While a more complex declaration (for a Grid, in this case),
    Packit a4aae4
        would look like this:
    Packit a4aae4
        \verbatim
    Packit a4aae4
        Grid {
    Packit a4aae4
        ARRAY:
    Packit a4aae4
        Int32 sst[time = 404][lat = 180][lon = 360];
    Packit a4aae4
        MAPS:
    Packit a4aae4
        Float64 time[time = 404];
    Packit a4aae4
        Float64 lat[lat = 180];
    Packit a4aae4
        Float64 lon[lon = 360];
    Packit a4aae4
        } sst;
    Packit a4aae4
        \endverbatim
    Packit a4aae4
    Packit a4aae4
        @brief Print an ASCII representation of the variable structure.
    Packit a4aae4
        @param out The output stream on which to print the
    Packit a4aae4
        declaration.
    Packit a4aae4
        @param space Each line of the declaration will begin with the
    Packit a4aae4
        characters in this string.  Usually used for leading spaces.
    Packit a4aae4
        @param print_semi A boolean value indicating whether to print a
    Packit a4aae4
        semicolon at the end of the declaration.
    Packit a4aae4
        @param constraint_info A boolean value indicating whether
    Packit a4aae4
        constraint information is to be printed with the declaration.
    Packit a4aae4
        If the value of this parameter is TRUE, <tt>print_decl()</tt> prints
    Packit a4aae4
        the value of the variable's <tt>send_p()</tt> flag after the
    Packit a4aae4
        declaration.
    Packit a4aae4
        @param constrained If this boolean value is TRUE, the variable's
    Packit a4aae4
        declaration is only printed if is the <tt>send_p()</tt> flag is TRUE.
    Packit a4aae4
        If a constraint expression is in place, and this variable is not
    Packit a4aae4
        requested, the <tt>send_p()</tt> flag is FALSE.
    Packit a4aae4
    Packit a4aae4
        @see DDS
    Packit a4aae4
        @see DDS::CE
    Packit a4aae4
     */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_decl(ostream &out, string space, bool print_semi,
    Packit a4aae4
        bool constraint_info, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        // if printing the constrained declaration, exit if this variable was not
    Packit a4aae4
        // selected.
    Packit a4aae4
        if (constrained && !send_p())
    Packit a4aae4
            return;
    Packit a4aae4
    Packit a4aae4
        out << space << type_name() << " " << id2www(name()) ;
    Packit a4aae4
    Packit a4aae4
        if (constraint_info) {
    Packit a4aae4
            if (send_p())
    Packit a4aae4
                out << ": Send True" ;
    Packit a4aae4
            else
    Packit a4aae4
                out << ": Send False" ;
    Packit a4aae4
        }
    Packit a4aae4
    Packit a4aae4
        if (print_semi)
    Packit a4aae4
            out << ";\n" ;
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Prints the value of the variable, with its declaration. This
    Packit a4aae4
    function is primarily intended for debugging DODS
    Packit a4aae4
    applications. However, it can be overloaded and used to do
    Packit a4aae4
    some useful things. Take a look at the asciival and writeval
    Packit a4aae4
    clients, both of which overload this to output the values of
    Packit a4aae4
    variables in different ways.
    Packit a4aae4
    Packit a4aae4
    @brief Prints the value of the variable.
    Packit a4aae4
    Packit a4aae4
    @param out The output stream on which to print the value.
    Packit a4aae4
    @param space This value is passed to the print_decl()
    Packit a4aae4
    function, and controls the leading spaces of the output.
    Packit a4aae4
    @param print_decl_p A boolean value controlling whether the
    Packit a4aae4
    variable declaration is printed as well as the value. */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::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
    /** Write the XML representation of this variable. This method is used to
    Packit a4aae4
        build the DDX XML response.
    Packit a4aae4
        @param out Destination.
    Packit a4aae4
        @param space Use this to indent child declarations. Default is "".
    Packit a4aae4
        @param constrained If true, only print this if it's part part of the
    Packit a4aae4
        current projection. Default is False.
    Packit a4aae4
        @deprecated */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_xml(FILE *out, string space, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        XMLWriter xml(space);
    Packit a4aae4
        print_xml_writer(xml, constrained);
    Packit a4aae4
        fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Write the XML representation of this variable. This method is used to
    Packit a4aae4
        build the DDX XML response.
    Packit a4aae4
        @param out Destination output stream
    Packit a4aae4
        @param space Use this to indent child declarations. Default is "".
    Packit a4aae4
        @param constrained If true, only print this if it's part part of the
    Packit a4aae4
        current projection. Default is False.
    Packit a4aae4
        @deprecated */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_xml(ostream &out, string space, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        XMLWriter xml(space);
    Packit a4aae4
        print_xml_writer(xml, constrained);
    Packit a4aae4
        out << xml.get_doc();
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Write the XML representation of this variable. This method is used to
    Packit a4aae4
        build the DDX XML response.
    Packit a4aae4
        @param out Destination output stream
    Packit a4aae4
        @param space Use this to indent child declarations. Default is "".
    Packit a4aae4
        @param constrained If true, only print this if it's part part of the
    Packit a4aae4
        current projection. Default is False. */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_xml_writer(XMLWriter &xml, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        if (constrained && !send_p())
    Packit a4aae4
            return;
    Packit a4aae4
    Packit a4aae4
        if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)type_name().c_str()) < 0)
    Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Could not write " + type_name() + " element");
    Packit a4aae4
    Packit a4aae4
        if (!name().empty())
    Packit a4aae4
            if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)name().c_str()) < 0)
    Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
    Packit a4aae4
    Packit a4aae4
        if (is_dap4())
    Packit a4aae4
            attributes()->print_dap4(xml);
    Packit a4aae4
    Packit a4aae4
        if (!is_dap4() && get_attr_table().get_size() > 0)
    Packit a4aae4
            get_attr_table().print_xml_writer(xml);
    Packit a4aae4
    Packit a4aae4
        if (xmlTextWriterEndElement(xml.get_writer()) < 0)
    Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Could not end " + type_name() + " element");
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** Write the DAP4 XML representation for this variable. This method is used
    Packit a4aae4
     * to build the DAP4 DMR response object.
    Packit a4aae4
     *
    Packit a4aae4
     * @param xml An XMLWriter that will do the serialization
    Packit a4aae4
     * @param constrained True if the response should show the variables subject
    Packit a4aae4
     * to the current constraint expression.
    Packit a4aae4
     */
    Packit a4aae4
    void
    Packit a4aae4
    BaseType::print_dap4(XMLWriter &xml, bool constrained)
    Packit a4aae4
    {
    Packit a4aae4
        print_xml_writer(xml, constrained);
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    // Compares the object's current state with the semantics of a particular
    Packit a4aae4
    // type. This will typically be defined in ctor classes (which have
    Packit a4aae4
    // complicated semantics). For BaseType, an object is semantically correct if
    Packit a4aae4
    // it has both a non-null name and type.
    Packit a4aae4
    //
    Packit a4aae4
    // NB: This is not the same as an invariant -- during the parse objects exist
    Packit a4aae4
    // but have no name. Also, the bool ALL defaults to false for BaseType. It is
    Packit a4aae4
    // used by children of CtorType.
    Packit a4aae4
    //
    Packit a4aae4
    // Returns: true if the object is semantically correct, false otherwise.
    Packit a4aae4
    Packit a4aae4
    /** This function checks the class instance for internal
    Packit a4aae4
        consistency.  This is important to check for complex constructor
    Packit a4aae4
        classes.  For BaseType, an object is semantically correct if it
    Packit a4aae4
        has both a non-null name and type.
    Packit a4aae4
    Packit a4aae4
        For example, an Int32 instance would return FALSE if it had no
    Packit a4aae4
        name or no type defined.  A Grid instance might return FALSE for
    Packit a4aae4
        more complex reasons, such as having Map arrays of the wrong
    Packit a4aae4
        size or shape.
    Packit a4aae4
    Packit a4aae4
        This function is used by the DDS class, and will rarely, if
    Packit a4aae4
        ever, be explicitly called by a DODS application program.  A
    Packit a4aae4
        variable must pass this test before it is sent, but there may be
    Packit a4aae4
        many other stages in a retrieve operation where it would fail.
    Packit a4aae4
    Packit a4aae4
        @brief Compare an object's current state with the semantics of its
    Packit a4aae4
        type.
    Packit a4aae4
        @return Returns FALSE when the current state violates some
    Packit a4aae4
        aspect of the type semantics, TRUE otherwise.
    Packit a4aae4
    Packit a4aae4
        @param msg A returned string, containing a message indicating
    Packit a4aae4
        the source of any problem.
    Packit a4aae4
        @param all For complex constructor types (Grid,
    Packit a4aae4
        Sequence, Structure), this flag indicates whether to check the
    Packit a4aae4
        semantics of the member variables, too.
    Packit a4aae4
    Packit a4aae4
        @see DDS::check_semantics
    Packit a4aae4
     */
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::check_semantics(string &msg, bool)
    Packit a4aae4
    {
    Packit a4aae4
        bool sem = (d_type != dods_null_c && name().length());
    Packit a4aae4
    Packit a4aae4
        if (!sem)
    Packit a4aae4
            msg = "Every variable must have both a name and a type\n";
    Packit a4aae4
    Packit a4aae4
        return sem;
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /** This method contains the relational operators used by the constraint
    Packit a4aae4
        expression evaluator in the DDS class. Each class that wants to be able
    Packit a4aae4
        to evaluate relational expressions must overload this function. The
    Packit a4aae4
        implementation in BaseType throws an InternalErr exception. The DAP
    Packit a4aae4
        library classes Byte, ..., Url provide specializations of this method. It
    Packit a4aae4
        is not meaningful for classes such as Array because relational
    Packit a4aae4
        expressions using Array are not supported.
    Packit a4aae4
    Packit a4aae4
        The op argument refers to a table generated by bison from
    Packit a4aae4
        the constraint expression parser.  Use statements like the
    Packit a4aae4
        following to correctly interpret its value:
    Packit a4aae4
    Packit a4aae4
        \verbatim
    Packit a4aae4
        switch (op) {
    Packit a4aae4
            case EQUAL: return i1 == i2;
    Packit a4aae4
            case NOT_EQUAL: return i1 != i2;
    Packit a4aae4
            case GREATER: return i1 > i2;
    Packit a4aae4
            case GREATER_EQL: return i1 >= i2;
    Packit a4aae4
            case LESS: return i1 < i2;
    Packit a4aae4
            case LESS_EQL: return i1 <= i2;
    Packit a4aae4
            case REGEXP: throw Error("Regular expressions are not supported for integer values");
    Packit a4aae4
            default: throw Error("Unknown operator");
    Packit a4aae4
        }
    Packit a4aae4
        \endverbatim
    Packit a4aae4
    Packit a4aae4
        This function is used by the constraint expression evaluator.
    Packit a4aae4
    Packit a4aae4
        @brief Evaluate relational operators.
    Packit a4aae4
        @param b Compare the value of this instance with \e b.
    Packit a4aae4
        @param op An integer index indicating which relational operator
    Packit a4aae4
        is implied. Choose one from the following: <tt>EQUAL</tt>,
    Packit a4aae4
        <tt>NOT_EQUAL</tt>, <tt>GREATER</tt>, <tt>GREATER_EQL</tt>,
    Packit a4aae4
        <tt>LESS</tt>, <tt>LESS_EQL</tt>, and <tt>REGEXP</tt>.
    Packit a4aae4
        @return The boolean value of the comparison.
    Packit a4aae4
        @see BaseType::d4_ops(BaseType *, int)
    Packit a4aae4
     */
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::ops(BaseType *, int)
    Packit a4aae4
    {
    Packit a4aae4
        // Even though ops is a public method, it can never be called because
    Packit a4aae4
        // they will never have a BaseType object since this class is abstract,
    Packit a4aae4
        // however any of the child classes could by mistake call BaseType::ops
    Packit a4aae4
        // so this is an internal error. Jose Garcia
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Unimplemented operator.");
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /**
    Packit a4aae4
     * @brief Evaluator a relop for DAP4
    Packit a4aae4
     *
    Packit a4aae4
     * This method is used by the filter expression evaluation code in DAP4.
    Packit a4aae4
     * Each of the 'data type' classes that support relops must overload this
    Packit a4aae4
     * method. In an expression of the form arg1 op arg2, this object is arg1,
    Packit a4aae4
     * the parameter 'b' is arg2 and op is the relational operator.
    Packit a4aae4
     *
    Packit a4aae4
     * @note I used the same relop codes for DAP4 as in the DAP2 parser/scanner
    Packit a4aae4
     * which makes for some coupling between them, but cuts way down on the
    Packit a4aae4
     * duplication of the evaluator logic, which is somewhat involved.
    Packit a4aae4
     *
    Packit a4aae4
     * @param b The second argument in the relational expression
    Packit a4aae4
     * @param op The infix relational operator
    Packit a4aae4
     * @return True if the expression is true, False otherwise.
    Packit a4aae4
     */
    Packit a4aae4
    bool
    Packit a4aae4
    BaseType::d4_ops(BaseType *, int)
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Unimplemented operator.");
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    /**
    Packit a4aae4
     * @brief How many bytes does this use
    Packit a4aae4
     * Return the number of bytes of storage this variable uses. For scalar types,
    Packit a4aae4
     * this is pretty simple (an int32 uses 4 bytes, etc.). For arrays and Constructors,
    Packit a4aae4
     * it is a bit more complex. Note that a scalar String variable uses sizeof(String*)
    Packit a4aae4
     * bytes, not the length of the string. In other words, the value returned is
    Packit a4aae4
     * independent of the type. Also note width() of a String array returns the number of
    Packit a4aae4
     * elements in the array times sizeof(String*). That is, each different array size
    Packit a4aae4
     * is a different data type.
    Packit a4aae4
     *
    Packit a4aae4
     * @param constrained Should the current constraint be taken into account?
    Packit a4aae4
     * @return Bytes of storage
    Packit a4aae4
     */
    Packit a4aae4
    unsigned int
    Packit a4aae4
    BaseType::width(bool /* constrained */) const
    Packit a4aae4
    {
    Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "not implemented");
    Packit a4aae4
    #if 0
    Packit a4aae4
        return width(constrained);
    Packit a4aae4
    #endif
    Packit a4aae4
    }
    Packit a4aae4
    Packit a4aae4
    } // namespace libdap