Blame Vector.cc

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 1995-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 class Vector. This class is the basis for all the
Packit a4aae4
// vector-type classes in libdap's <Array, List>.
Packit a4aae4
//
Packit a4aae4
// 11/21/95 jhrg
Packit a4aae4
Packit a4aae4
#include "config.h"
Packit a4aae4
Packit a4aae4
#include <cstring>
Packit a4aae4
#include <cassert>
Packit a4aae4
Packit a4aae4
//#define DODS_DEBUG 1
Packit a4aae4
Packit a4aae4
#include <sstream>
Packit a4aae4
#include <vector>
Packit a4aae4
#include <algorithm>
Packit a4aae4
#include <typeinfo>
Packit a4aae4
Packit a4aae4
#include <stdint.h>
Packit a4aae4
Packit a4aae4
#include "crc.h"
Packit a4aae4
Packit a4aae4
#include "Vector.h"
Packit a4aae4
#include "Marshaller.h"
Packit a4aae4
#include "UnMarshaller.h"
Packit a4aae4
Packit a4aae4
#include "D4StreamMarshaller.h"
Packit a4aae4
#include "D4StreamUnMarshaller.h"
Packit a4aae4
Packit a4aae4
#include "D4Enum.h"
Packit a4aae4
Packit a4aae4
#include "Type.h"
Packit a4aae4
#include "dods-datatypes.h"
Packit a4aae4
#include "escaping.h"
Packit a4aae4
#include "util.h"
Packit a4aae4
#include "debug.h"
Packit a4aae4
#include "InternalErr.h"
Packit a4aae4
Packit a4aae4
#undef CLEAR_LOCAL_DATA
Packit a4aae4
Packit a4aae4
using std::cerr;
Packit a4aae4
using std::endl;
Packit a4aae4
Packit a4aae4
namespace libdap {
Packit a4aae4
Packit a4aae4
void Vector::m_duplicate(const Vector & v)
Packit a4aae4
{
Packit a4aae4
    d_length = v.d_length;
Packit a4aae4
Packit a4aae4
    // _var holds the type of the elements. That is, it holds a BaseType
Packit a4aae4
    // which acts as a template for the type of each element.
Packit a4aae4
    if (v.d_proto) {
Packit a4aae4
        d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
Packit a4aae4
        d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        d_proto = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
Packit a4aae4
    // d_compound_buf is used when the Vector holds non-numeric data (including strings
Packit a4aae4
    // although it used to be that was not the case jhrg 2/10/05) while d_buf
Packit a4aae4
    // holds numeric values.
Packit a4aae4
    if (v.d_compound_buf.empty()) {
Packit a4aae4
        d_compound_buf = v.d_compound_buf;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        // Failure to set the size will make the [] operator barf on the LHS
Packit a4aae4
        // of the assignment inside the loop.
Packit a4aae4
        d_compound_buf.resize(d_length);
Packit a4aae4
        for (int i = 0; i < d_length; ++i) {
Packit a4aae4
            // There's no need to call set_parent() for each element; we
Packit a4aae4
            // maintain the back pointer using the d_proto member. These
Packit a4aae4
            // instances are used to hold _values_ only while the d_proto
Packit a4aae4
            // field holds the type information for the elements.
Packit a4aae4
            d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // copy the strings. This copies the values.
Packit a4aae4
    d_str = v.d_str;
Packit a4aae4
Packit a4aae4
    // copy numeric values if there are any.
Packit a4aae4
    d_buf = 0; // init to null
Packit a4aae4
    if (v.d_buf) // only copy if data present
Packit a4aae4
        val2buf(v.d_buf); // store v's value in this's _BUF.
Packit a4aae4
Packit a4aae4
    d_capacity = v.d_capacity;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @return whether the type of this Vector is a cardinal type
Packit a4aae4
 * (i.e., stored in d_buf)
Packit a4aae4
 */
Packit a4aae4
bool Vector::m_is_cardinal_type() const
Packit a4aae4
{
Packit a4aae4
    // Not cardinal if no d_proto at all!
Packit a4aae4
    if (!d_proto) {
Packit a4aae4
        return false;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
        	// New cardinal types for DAP4
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
            return true;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
            // These must be handled differently.
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            return false;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            assert("Vector::var: Unrecognized type");
Packit a4aae4
            return false;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Create _buf so that it can store numElts of the
Packit a4aae4
 * (assumed) cardinal type.  This create storage for
Packit a4aae4
 * width() * numElts bytes.
Packit a4aae4
 * If _buf already exists, this DELETES IT and creates a new one.
Packit a4aae4
 * So don't use this if you want to keep the original _buf data around.
Packit a4aae4
 * This also sets the valueCapacity().
Packit a4aae4
 * @param numEltsOfType the number of elements of the cardinal type in var()
Packit a4aae4
 that we want storage for.
Packit a4aae4
 * @return the size of the buffer created.
Packit a4aae4
 * @exception if the Vector's type is not cardinal type.
Packit a4aae4
 */
Packit a4aae4
unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Packit a4aae4
{
Packit a4aae4
    // Make sure we HAVE a _var, or we cannot continue.
Packit a4aae4
    if (!d_proto) {
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // Make sure we only do this for the correct data types.
Packit a4aae4
    if (!m_is_cardinal_type()) {
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    m_delete_cardinal_data_buffer();
Packit a4aae4
Packit a4aae4
    // Handle this special case where this is an array that holds no values
Packit a4aae4
    if (numEltsOfType == 0)
Packit a4aae4
        return 0;
Packit a4aae4
Packit a4aae4
    // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
Packit a4aae4
    unsigned int bytesPerElt = d_proto->width();
Packit a4aae4
    unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
Packit a4aae4
    d_buf = new char[bytesNeeded];
Packit a4aae4
Packit a4aae4
    d_capacity = numEltsOfType;
Packit a4aae4
    return bytesNeeded;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Delete d_buf and zero it and d_capacity out */
Packit a4aae4
void Vector::m_delete_cardinal_data_buffer()
Packit a4aae4
{
Packit a4aae4
	delete[] d_buf;
Packit a4aae4
	d_buf = 0;
Packit a4aae4
	d_capacity = 0;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Helper to reduce cut and paste in the virtual's.
Packit a4aae4
 *
Packit a4aae4
 */
Packit a4aae4
template<class CardType>
Packit a4aae4
void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
Packit a4aae4
{
Packit a4aae4
    if (numElts < 0) {
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
Packit a4aae4
    }
Packit a4aae4
    if (!fromArray) {
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
Packit a4aae4
    }
Packit a4aae4
    set_length(numElts);
Packit a4aae4
    m_create_cardinal_data_buffer_for_type(numElts);
Packit a4aae4
    memcpy(d_buf, fromArray, numElts * sizeof(CardType));
Packit a4aae4
    set_read_p(true);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** The Vector constructor requires the name of the variable to be
Packit a4aae4
 created, and a pointer to an object of the type the Vector is to
Packit a4aae4
 hold.  The name may be omitted, which will create a nameless
Packit a4aae4
 variable.  The template object may not be omitted.
Packit a4aae4
Packit a4aae4
 @param n A string containing the name of the variable to be
Packit a4aae4
 created.
Packit a4aae4
 @param v A pointer to a prototype for elements.
Packit a4aae4
 @param t The type of the resulting Vector object, from the Type
Packit a4aae4
 enum list.  There is no DAP2 Vector object, so all uses of this
Packit a4aae4
 method will be from the Array class.  This defaults to
Packit a4aae4
 <tt>dods_null_c</tt>.
Packit a4aae4
Packit a4aae4
 @see Type
Packit a4aae4
 @brief The Vector constructor.  */
Packit a4aae4
Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
Packit a4aae4
    BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
Packit a4aae4
{
Packit a4aae4
    if (v)
Packit a4aae4
        add_var(v);
Packit a4aae4
Packit a4aae4
    DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
Packit a4aae4
    if (d_proto)
Packit a4aae4
        d_proto->set_parent(this);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** The Vector server-side constructor requires the name of the variable
Packit a4aae4
 to be created, the dataset name from which this Vector is created, and
Packit a4aae4
 a pointer to an object of the type the Vector is to hold.  The
Packit a4aae4
 name may be omitted, which will create a nameless variable.
Packit a4aae4
 The template object may not be omitted.
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 dataset name from which the variable is
Packit a4aae4
 being created.
Packit a4aae4
 @param v A pointer to a prototype for elements.
Packit a4aae4
 @param t The type of the resulting Vector object, from the Type
Packit a4aae4
 enum list.  There is no DAP2 Vector object, so all uses of this
Packit a4aae4
 method will be from the Array class.  This defaults to
Packit a4aae4
 <tt>dods_null_c</tt>.
Packit a4aae4
Packit a4aae4
 @see Type
Packit a4aae4
 @brief The Vector constructor.  */
Packit a4aae4
Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
Packit a4aae4
    BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
Packit a4aae4
{
Packit a4aae4
    if (v)
Packit a4aae4
        add_var(v);
Packit a4aae4
Packit a4aae4
    DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
Packit a4aae4
    if (d_proto)
Packit a4aae4
        d_proto->set_parent(this);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** The Vector copy constructor. */
Packit a4aae4
Vector::Vector(const Vector & rhs) :
Packit a4aae4
    BaseType(rhs)
Packit a4aae4
{
Packit a4aae4
    DBG2(cerr << "Entering Vector const ctor for object: " << this <<
Packit a4aae4
            endl); DBG2(cerr << "RHS: " << &rhs << endl);
Packit a4aae4
Packit a4aae4
    m_duplicate(rhs);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Vector::~Vector()
Packit a4aae4
{
Packit a4aae4
    DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
Packit a4aae4
Packit a4aae4
    delete d_proto;
Packit a4aae4
    d_proto = 0;
Packit a4aae4
Packit a4aae4
    // Clears all buffers
Packit a4aae4
    clear_local_data();
Packit a4aae4
Packit a4aae4
    DBG2(cerr << "Exiting ~Vector" << endl);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Vector & Vector::operator=(const Vector & rhs)
Packit a4aae4
{
Packit a4aae4
    if (this == &rhs)
Packit a4aae4
        return *this;
Packit a4aae4
Packit a4aae4
    dynamic_cast<BaseType &> (*this) = rhs;
Packit a4aae4
Packit a4aae4
    m_duplicate(rhs);
Packit a4aae4
Packit a4aae4
    return *this;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Vector::set_name(const std::string& name)
Packit a4aae4
{
Packit a4aae4
    BaseType::set_name(name);
Packit a4aae4
    // We need to set the prototype name as well since
Packit a4aae4
    // this is what gets output in the dds!  Otherwise, there's a mismatch.
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        d_proto->set_name(name);
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
int Vector::element_count(bool leaves)
Packit a4aae4
{
Packit a4aae4
    if (!leaves)
Packit a4aae4
        return 1;
Packit a4aae4
    else
Packit a4aae4
    	return d_proto->element_count(leaves);
Packit a4aae4
        // var() only works for simple types!
Packit a4aae4
        // jhrg 8/19/13 return var(0)->element_count(leaves);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// These mfuncs set the _send_p and _read_p fields of BaseType. They differ
Packit a4aae4
// from BaseType's version in that they set both the Vector object's copy of
Packit a4aae4
// _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
Packit a4aae4
// is a scalar, but does matter when it is an aggregate.
Packit a4aae4
Packit a4aae4
/** This function sets the <tt>send_p</tt> flag for both the Vector itself
Packit a4aae4
 and its element template.  This does not matter much when the
Packit a4aae4
 Vector contains simple data types, but does become significant
Packit a4aae4
 when the Vector contains compound types.
Packit a4aae4
Packit a4aae4
 @brief Indicates that the data is ready to send. */
Packit a4aae4
void Vector::set_send_p(bool state)
Packit a4aae4
{
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        d_proto->set_send_p(state);
Packit a4aae4
Packit a4aae4
        // because some code may depend on the BaseType*s held in d_compound_buf
Packit a4aae4
        // behaving as if they are 'ordinary' DAP variables, make sure their send_p
Packit a4aae4
        // flag is set if they exist. Because space in the vector is allocated
Packit a4aae4
        // before values (BaseType*s) are added, check for nulls and limit the
Packit a4aae4
        // iteration to only those elements actually in the object including any
Packit a4aae4
        // constraints that may have been applied - these are values not declarations.
Packit a4aae4
        // jhrg 5/13/16
Packit a4aae4
        switch (d_proto->type()) {
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            if (d_compound_buf.size() > 0) {
Packit a4aae4
                for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
Packit a4aae4
                    if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType::set_send_p(state);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** This function sets the <tt>read_p</tt> flag for both the Vector itself
Packit a4aae4
 and its element template.  This does not matter much when the
Packit a4aae4
 Vector contains simple data types, but does become significant
Packit a4aae4
 when the Vector contains compound types.
Packit a4aae4
Packit a4aae4
 @brief Indicates that the data is ready to send.  */
Packit a4aae4
void Vector::set_read_p(bool state)
Packit a4aae4
{
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        d_proto->set_read_p(state);
Packit a4aae4
Packit a4aae4
        // See comment above.
Packit a4aae4
        switch (d_proto->type()) {
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            if (d_compound_buf.size() > 0) {
Packit a4aae4
                for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
Packit a4aae4
                    if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
Packit a4aae4
                }
Packit a4aae4
            }
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    BaseType::set_read_p(state);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns a copy of the template array element. If the Vector contains
Packit a4aae4
 simple data types, the template will contain the value of the last
Packit a4aae4
 vector element accessed with the Vector::var(int i) function,
Packit a4aae4
 if any. If no such access has been made, or if the Vector contains
Packit a4aae4
 compound data types, the value held by the template instance is
Packit a4aae4
 undefined.
Packit a4aae4
Packit a4aae4
 Note that the parameter exact_match is not used by this mfunc.
Packit a4aae4
Packit a4aae4
 @param n The name of the variable to find.
Packit a4aae4
 @param exact Unused.
Packit a4aae4
 @param s Pointer to a BaseType Pointer Stack. Use this stack to record
Packit a4aae4
 the path to the variable. By default this pointer is null, in which case
Packit a4aae4
 it is not used.
Packit a4aae4
Packit a4aae4
 @return A pointer to the BaseType if found, otherwise null.
Packit a4aae4
 @see Vector::var */
Packit a4aae4
BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
Packit a4aae4
{
Packit a4aae4
    string name = www2id(n);
Packit a4aae4
    DBG2(cerr << "Vector::var: Looking for " << name << endl);
Packit a4aae4
Packit a4aae4
    if (name == "" || d_proto->name() == name) {
Packit a4aae4
        if (s)
Packit a4aae4
            s->push(this);
Packit a4aae4
        return d_proto;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // If this is a Vector of constructor types, look for 'name' recursively.
Packit a4aae4
    // Make sure to check for the case where name is the default (the empty
Packit a4aae4
    // string). 9/1/98 jhrg
Packit a4aae4
    if (d_proto->is_constructor_type()) {
Packit a4aae4
        BaseType *result = d_proto->var(name, exact, s);
Packit a4aae4
        if (result && s)
Packit a4aae4
            s->push(this);
Packit a4aae4
        return result;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return NULL;
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 above when exact_match is false. In addition to
Packit a4aae4
 returning a pointer to the variable, it pushes onto s a
Packit a4aae4
 BaseType pointer to each constructor type that ultimately contains
Packit a4aae4
 name.
Packit a4aae4
Packit a4aae4
 @param n Find the variable whose name is name.
Packit a4aae4
 @param s Record the path to name.
Packit a4aae4
 @return A pointer to the named variable. */
Packit a4aae4
BaseType *Vector::var(const string & n, btp_stack & s)
Packit a4aae4
{
Packit a4aae4
    string name = www2id(n);
Packit a4aae4
Packit a4aae4
    if (d_proto->is_constructor_type())
Packit a4aae4
        return d_proto->var(name, s);
Packit a4aae4
    else {
Packit a4aae4
        s.push((BaseType *) this);
Packit a4aae4
        return d_proto;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns a pointer to the specified Vector element.  The return
Packit a4aae4
 pointer will reference the element itself, so multiple calls to this
Packit a4aae4
 method should save each value before making the next call.
Packit a4aae4
Packit a4aae4
 @param i The index of the desired Vector element.  Zero
Packit a4aae4
 indicates the first element of the Vector.
Packit a4aae4
 @return A pointer to a BaseType class instance containing
Packit a4aae4
 the value of the indicated element. The BaseType pointer is locally
Packit a4aae4
 maintained and should not be deleted or referenced. Extract the value
Packit a4aae4
 right after the method returns.
Packit a4aae4
 @see BaseType::var */
Packit a4aae4
BaseType *Vector::var(unsigned int i)
Packit a4aae4
{
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            // Transfer the ith value to the BaseType *d_proto
Packit a4aae4
            d_proto->val2buf(d_buf + (i * d_proto->width()));
Packit a4aae4
            return d_proto;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            d_proto->val2buf(&d_str[i]);
Packit a4aae4
            return d_proto;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_array_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            return d_compound_buf[i];
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw Error ("Vector::var: Unrecognized type");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return 0;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns the number of bytes needed to hold the entire
Packit a4aae4
 array.  This is equal to \c length() (the number of elements in
Packit a4aae4
 in the array) times the width of each
Packit a4aae4
 element.
Packit a4aae4
Packit a4aae4
 @brief Returns the width of the data, in bytes. */
Packit a4aae4
unsigned int Vector::width(bool constrained) const
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
	assert(d_proto);
Packit a4aae4
Packit a4aae4
    return length() * d_proto->width(constrained);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Returns the number of elements in the vector. Note that some
Packit a4aae4
 child classes of Vector use the length of -1 as a flag value.
Packit a4aae4
Packit a4aae4
 @see Vector::append_dim */
Packit a4aae4
int Vector::length() const
Packit a4aae4
{
Packit a4aae4
    return d_length;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Sets the length of the vector.  This function does not allocate
Packit a4aae4
 any new space. */
Packit a4aae4
void Vector::set_length(int l)
Packit a4aae4
{
Packit a4aae4
    d_length = l;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Resizes a Vector.  If the input length is greater than the
Packit a4aae4
 current length of the Vector, new memory is allocated (the
Packit a4aae4
 Vector moved if necessary), and the new entries are appended to
Packit a4aae4
 the end of the array and padded with Null values.  If the input
Packit a4aae4
 length is shorter, the tail values are discarded.
Packit a4aae4
Packit a4aae4
 @note This method is applicable to the compound types only.
Packit a4aae4
 */
Packit a4aae4
void Vector::vec_resize(int l)
Packit a4aae4
{
Packit a4aae4
    // I added this check, which alters the behavior of the method. jhrg 8/14/13
Packit a4aae4
    if (m_is_cardinal_type())
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
Packit a4aae4
Packit a4aae4
    // Use resize() since other parts of the code use operator[]. Note that size() should
Packit a4aae4
    // be used when resize() is used. Using capacity() creates problems as noted in the
Packit a4aae4
    // comment in set_vec_nocopy(). jhrg 5/19/17
Packit a4aae4
    d_compound_buf.resize(l, 0); // Fill with NULLs
Packit a4aae4
    d_capacity = d_compound_buf.size(); // size in terms of number of elements.
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief read data into a variable for later use
Packit a4aae4
Packit a4aae4
 Most uses of a variable are to either serialize its data to a stream of
Packit a4aae4
 some sort or to read values from some stream and intern those in the
Packit a4aae4
 variable for later use. These operations are perform by serialize()
Packit a4aae4
 and deserialize() which follow. This function performs essentially both
Packit a4aae4
 of these operations without actually using a stream device. The data are
Packit a4aae4
 read using the read() method(s) and loaded into the variables directly.
Packit a4aae4
Packit a4aae4
 This method is intended to be used by objects which transform DAP objects
Packit a4aae4
 like the DataDDS into an ASCII CSV representation.
Packit a4aae4
Packit a4aae4
 @note A DAP2-only method
Packit a4aae4
Packit a4aae4
 @param eval A reference to a constraint evaluator
Packit a4aae4
 @param dds The complete DDS to which this variable belongs */
Packit a4aae4
void Vector::intern_data(ConstraintEvaluator &eval, DDS &dds)
Packit a4aae4
{
Packit a4aae4
    DBG(cerr << "Vector::intern_data: " << name() << endl);
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read(); // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    // length() is not capacity; it must be set explicitly in read().
Packit a4aae4
    int num = length();
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            // For these cases, read() puts the data into d_buf,
Packit a4aae4
        	// which is what we need.
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            // For these cases, read() will put the data into d_str[],
Packit a4aae4
        	// which is also what we need.
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
            // This is an error since there can never be an Array of Array.
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            DBG(cerr << "Vector::intern_data: found ctor" << endl);
Packit a4aae4
            // For these cases, we need to call read() for each of the 'num'
Packit a4aae4
            // elements in the 'd_compound_buf[]' array of BaseType object pointers.
Packit a4aae4
            //
Packit a4aae4
            // I changed the test here from '... = 0' to '... < num' to accommodate
Packit a4aae4
            // the case where the array is zero-length.
Packit a4aae4
            if (d_compound_buf.capacity() < (unsigned)num)
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
Packit a4aae4
Packit a4aae4
            for (int i = 0; i < num; ++i)
Packit a4aae4
                d_compound_buf[i]->intern_data(eval, dds);
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief Serialize a Vector.
Packit a4aae4
Packit a4aae4
 This uses the Marshaler class to encode each element of a cardinal
Packit a4aae4
 array. For Arrays of Str and Url types, send the element count over
Packit a4aae4
 as a prefix to the data so that deserialize will know how many elements
Packit a4aae4
 to read.
Packit a4aae4
Packit a4aae4
 NB: Arrays of cardinal types must already be in BUF (in the local machine's
Packit a4aae4
 representation) before this call is made.
Packit a4aae4
 */
Packit a4aae4
Packit a4aae4
bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
Packit a4aae4
{
Packit a4aae4
#if 0
Packit a4aae4
    dds.timeout_on();
Packit a4aae4
#endif
Packit a4aae4
    // Added to streamline zero-length arrays. Not needed for correct function,
Packit a4aae4
    // but explicitly handling this case here makes the code easier to follow.
Packit a4aae4
    // In libdap::Vector::val2buf() there is a test that will catch the zero-length
Packit a4aae4
    // case as well. We still need to call serialize since it will write size
Packit a4aae4
    // information that the client depends on. jhrg 2/17/16
Packit a4aae4
    if (length() == 0)
Packit a4aae4
        set_read_p(true);
Packit a4aae4
    else if (!read_p())
Packit a4aae4
        read(); // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    if (ce_eval && !eval.eval_selection(dds, dataset()))
Packit a4aae4
        return true;
Packit a4aae4
#if 0
Packit a4aae4
    dds.timeout_off();
Packit a4aae4
#endif
Packit a4aae4
    // length() is not capacity; it must be set explicitly in read().
Packit a4aae4
    int num = length();
Packit a4aae4
Packit a4aae4
    bool status = false;
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
            m.put_vector(d_buf, num, *this);
Packit a4aae4
            status = true;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            m.put_vector(d_buf, num, d_proto->width(), *this);
Packit a4aae4
            status = true;
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            if (d_str.capacity() == 0)
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
Packit a4aae4
Packit a4aae4
            m.put_int(num);
Packit a4aae4
Packit a4aae4
            for (int i = 0; i < num; ++i)
Packit a4aae4
                m.put_str(d_str[i]);
Packit a4aae4
Packit a4aae4
            status = true;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            //Jose Garcia
Packit a4aae4
            // Not setting the capacity of d_compound_buf is an internal error.
Packit a4aae4
            if (d_compound_buf.capacity() == 0)
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
Packit a4aae4
Packit a4aae4
            m.put_int(num);
Packit a4aae4
            status = true;
Packit a4aae4
            for (int i = 0; i < num && status; ++i)
Packit a4aae4
                status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
#ifdef CLEAR_LOCAL_DATA
Packit a4aae4
    clear_local_data();
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
    return status;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
// Read an object from the network and internalize it. For a Vector this is
Packit a4aae4
// handled differently for a `cardinal' type. Vectors of Cardinals are
Packit a4aae4
// stored using the `C' representations because these objects often are used
Packit a4aae4
// to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
Packit a4aae4
// arrays of non-cardinal types are stored as Vectors of the C++ objects or
Packit a4aae4
// DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
Packit a4aae4
// Grid are vectors of the libdap Structure, ... classes).
Packit a4aae4
//
Packit a4aae4
// The boolean parameter REUSE determines whether internal storage is reused
Packit a4aae4
// or not. If true, the _buf member is assumed to be large enough to hold the
Packit a4aae4
// incoming cardinal data and is *not* reallocated. If false, new storage is
Packit a4aae4
// allocated. If the internal buffer has not yet been allocated, then this
Packit a4aae4
// parameter has no effect (i.e., storage is allocated). This parameter
Packit a4aae4
// effects storage for cardinal data only.
Packit a4aae4
//
Packit a4aae4
// Returns: True is successful, false otherwise.
Packit a4aae4
Packit a4aae4
bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
Packit a4aae4
{
Packit a4aae4
    unsigned int num;
Packit a4aae4
    unsigned i = 0;
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            um.get_int((int &) num);
Packit a4aae4
Packit a4aae4
            DBG(cerr << "Vector::deserialize: num = " << num << endl);
Packit a4aae4
            DBG(cerr << "Vector::deserialize: length = " << length() << endl);
Packit a4aae4
Packit a4aae4
            if (length() == -1)
Packit a4aae4
                set_length(num);
Packit a4aae4
Packit a4aae4
            if (num != (unsigned int) length())
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
Packit a4aae4
Packit a4aae4
            if (!d_buf || !reuse) {
Packit a4aae4
                // Make d_buf be large enough for length() elements of _var->type()
Packit a4aae4
            	// m_create...() deletes the old buffer.
Packit a4aae4
                m_create_cardinal_data_buffer_for_type(length());
Packit a4aae4
                DBG(cerr << "Vector::deserialize: allocating "
Packit a4aae4
                        << width() << " bytes for an array of "
Packit a4aae4
                        << length() << " " << d_proto->type_name() << endl);
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            // Added to accommodate zero-length arrays.
Packit a4aae4
            // Note that the rest of the cases will just send the size without data
Packit a4aae4
            // but that these calls trigger error testing in the UnMarshaller code.
Packit a4aae4
            // jhrg 1/28/16
Packit a4aae4
            if (num == 0)
Packit a4aae4
                return true;
Packit a4aae4
Packit a4aae4
            if (d_proto->type() == dods_byte_c)
Packit a4aae4
                um.get_vector((char **) &d_buf, num, *this);
Packit a4aae4
            else
Packit a4aae4
                um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
Packit a4aae4
Packit a4aae4
            DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            um.get_int((int &) num);
Packit a4aae4
Packit a4aae4
            if (length() == -1)
Packit a4aae4
                set_length(num);
Packit a4aae4
Packit a4aae4
            if (num != (unsigned int) length())
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
Packit a4aae4
Packit a4aae4
            d_str.resize((num > 0) ? num : 0); // Fill with NULLs
Packit a4aae4
            d_capacity = num; // capacity is number of strings we can fit.
Packit a4aae4
Packit a4aae4
            for (i = 0; i < num; ++i) {
Packit a4aae4
                string str;
Packit a4aae4
                um.get_str(str);
Packit a4aae4
                d_str[i] = str;
Packit a4aae4
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
            // Added jhrg 5/18/17
Packit a4aae4
            // This replaces a comment that was simply 'TO DO'
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Array of array!");
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            um.get_int((int &) num);
Packit a4aae4
Packit a4aae4
            if (length() == -1)
Packit a4aae4
                set_length(num);
Packit a4aae4
Packit a4aae4
            if (num != (unsigned int) length())
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
Packit a4aae4
Packit a4aae4
            vec_resize(num);
Packit a4aae4
Packit a4aae4
            for (i = 0; i < num; ++i) {
Packit a4aae4
                d_compound_buf[i] = d_proto->ptr_duplicate();
Packit a4aae4
                d_compound_buf[i]->deserialize(um, dds);
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown type!");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return false;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Vector::compute_checksum(Crc32 &checksum)
Packit a4aae4
{
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
        	checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
        	for (int64_t i = 0, e = length(); i < e; ++i)
Packit a4aae4
        		checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        	d_proto->compute_checksum(checksum);
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:	// No array of array
Packit a4aae4
        case dods_grid_c:	// No grids in DAP4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
Packit a4aae4
{
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read(); // read() throws Error and InternalErr
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
#if 0
Packit a4aae4
        	compute_checksum(checksum);
Packit a4aae4
#endif
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
            // Modified the assert here from '... != 0' to '... >= length())
Packit a4aae4
            // to accommodate the case of a zero-length array. jhrg 1/28/16
Packit a4aae4
            assert(d_compound_buf.capacity() >= (unsigned)length());
Packit a4aae4
Packit a4aae4
            for (int i = 0, e = length(); i < e; ++i)
Packit a4aae4
                d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:      // No Array of Array in DAP4 either...
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
        default:
Packit a4aae4
        	throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/)
Packit a4aae4
{
Packit a4aae4
    if (!read_p())
Packit a4aae4
        read(); // read() throws Error and InternalErr
Packit a4aae4
#if 0
Packit a4aae4
    if (filter && !eval.eval_selection(dmr, dataset()))
Packit a4aae4
        return true;
Packit a4aae4
#endif
Packit a4aae4
    int64_t num = length();	// The constrained length in elements
Packit a4aae4
Packit a4aae4
    DBG(cerr << __func__ << ", num: " << num << endl);
Packit a4aae4
Packit a4aae4
    // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
Packit a4aae4
    if (num == 0)
Packit a4aae4
        return;
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
            m.put_vector(d_buf, num);
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
        	m.put_vector(d_buf, num, d_proto->width());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
        	if (d_proto->width() == 1)
Packit a4aae4
        		m.put_vector(d_buf, num);
Packit a4aae4
        	else
Packit a4aae4
        		m.put_vector(d_buf, num, d_proto->width());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
            m.put_vector_float32(d_buf, num);
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            m.put_vector_float64(d_buf, num);
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            assert((int64_t)d_str.capacity() >= num);
Packit a4aae4
Packit a4aae4
            for (int64_t i = 0; i < num; ++i)
Packit a4aae4
                m.put_str(d_str[i]);
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
        	throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
            assert(d_compound_buf.capacity() >= 0);
Packit a4aae4
Packit a4aae4
            for (int64_t i = 0; i < num; ++i) {
Packit a4aae4
                DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
Packit a4aae4
                d_compound_buf[i]->serialize(m, dmr, filter);
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
        	throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
#ifdef CLEAR_LOCAL_DATA
Packit a4aae4
    clear_local_data();
Packit a4aae4
#endif
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void
Packit a4aae4
Vector::deserialize(D4StreamUnMarshaller &um, DMR &dmr)
Packit a4aae4
{
Packit a4aae4
    if (m_is_cardinal_type()) {
Packit a4aae4
        if (d_buf)
Packit a4aae4
            m_delete_cardinal_data_buffer();
Packit a4aae4
        if (!d_buf)
Packit a4aae4
            m_create_cardinal_data_buffer_for_type(length());
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
Packit a4aae4
Packit a4aae4
    // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
Packit a4aae4
    if (length() == 0)
Packit a4aae4
        return;
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        	um.get_vector((char *)d_buf, length());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
        	um.get_vector((char *)d_buf, length(), d_proto->width());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
        	if (d_proto->width() == 1)
Packit a4aae4
        		um.get_vector((char *)d_buf, length());
Packit a4aae4
        	else
Packit a4aae4
        		um.get_vector((char *)d_buf, length(), d_proto->width());
Packit a4aae4
        	break;
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
            um.get_vector_float32((char *)d_buf, length());
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
        	um.get_vector_float64((char *)d_buf, length());
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c: {
Packit a4aae4
        	int64_t len = length();
Packit a4aae4
            d_str.resize((len > 0) ? len : 0); // Fill with NULLs
Packit a4aae4
            d_capacity = len; // capacity is number of strings we can fit.
Packit a4aae4
Packit a4aae4
            for (int64_t i = 0; i < len; ++i) {
Packit a4aae4
                um.get_str(d_str[i]);
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
        	throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c: {
Packit a4aae4
            vec_resize(length());
Packit a4aae4
Packit a4aae4
            for (int64_t i = 0, end = length(); i < end; ++i) {
Packit a4aae4
                d_compound_buf[i] = d_proto->ptr_duplicate();
Packit a4aae4
                d_compound_buf[i]->deserialize(um, dmr);
Packit a4aae4
            }
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
        	throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Unknown type.");
Packit a4aae4
            break;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Copies data into the class instance buffer.  This function
Packit a4aae4
 assumes that the input \e val points to memory which
Packit a4aae4
 contains, in row major order, enough elements of the correct
Packit a4aae4
 type to fill the array. For an array of a cardinal type the
Packit a4aae4
 memory is simply copied in whole into the Vector buffer.
Packit a4aae4
Packit a4aae4
 If the variable has already been constrained, this method will load only
Packit a4aae4
 number of values/bytes specified by that constraint and will load them
Packit a4aae4
 into the 'front' of the object's internal buffer. This is where serialize()
Packit a4aae4
 expects to find the data.
Packit a4aae4
Packit a4aae4
 For a Vector of Str (OPeNDAP Strings), this assumes \e val points to an
Packit a4aae4
 array of C++ strings.
Packit a4aae4
Packit a4aae4
 This method should not be used for Structure, Sequence or Grid.
Packit a4aae4
Packit a4aae4
 @brief Reads data into the Vector buffer.
Packit a4aae4
 @exception InternalErr Thrown if called for Structure, Sequence or
Packit a4aae4
 Grid.
Packit a4aae4
 @return The number of bytes used by the array.
Packit a4aae4
 @param val A pointer to the input data.
Packit a4aae4
 @param reuse A boolean value, indicating whether the class
Packit a4aae4
 internal data storage can be reused or not.  If this argument is
Packit a4aae4
 TRUE, the class buffer is assumed to be large enough to hold the
Packit a4aae4
 incoming data, and it is not reallocated.  If FALSE, new
Packit a4aae4
 storage is allocated.  If the internal buffer has not been
Packit a4aae4
 allocated at all, this argument has no effect. */
Packit a4aae4
unsigned int Vector::val2buf(void *val, bool reuse)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
Packit a4aae4
    // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
Packit a4aae4
    if (!val && length() == 0)
Packit a4aae4
        return 0;
Packit a4aae4
Packit a4aae4
    // I *think* this method has been mainly designed to be use by read which
Packit a4aae4
    // is implemented in the surrogate library. Passing NULL as a pointer to
Packit a4aae4
    // this method will be an error of the creator of the surrogate library.
Packit a4aae4
    // Even though I recognize the fact that some methods inside libdap++ can
Packit a4aae4
    // call val2buf, I think by now no coding bugs such as misusing val2buf
Packit a4aae4
    // will be in libdap++, so it will be an internal error from the
Packit a4aae4
    // surrogate library.
Packit a4aae4
    if (!val)
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
#if 0
Packit a4aae4
        	if (d_buf && !reuse)
Packit a4aae4
                m_delete_cardinal_data_buffer();
Packit a4aae4
#endif
Packit a4aae4
            // First time or no reuse (free'd above)
Packit a4aae4
            if (!d_buf || !reuse)
Packit a4aae4
                m_create_cardinal_data_buffer_for_type(length());
Packit a4aae4
Packit a4aae4
            // width(true) returns the size in bytes given the constraint
Packit a4aae4
            memcpy(d_buf, val, width(true));
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            // Assume val points to an array of C++ string objects. Copy
Packit a4aae4
            // them into the vector<string> field of this object.
Packit a4aae4
            // Note: d_length is the number of elements in the Vector
Packit a4aae4
            d_str.resize(d_length);
Packit a4aae4
            d_capacity = d_length;
Packit a4aae4
            for (int i = 0; i < d_length; ++i)
Packit a4aae4
                d_str[i] = *(static_cast<string *> (val) + i);
Packit a4aae4
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
Packit a4aae4
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    return width(true);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Copies data from the Vector buffer.  This function assumes that
Packit a4aae4
 val points to an array large enough to hold N instances of
Packit a4aae4
 the `C' representation of the \e numeric element type or C++ string
Packit a4aae4
 objects. Never call this method for constructor types Structure,
Packit a4aae4
 Sequence or Grid.
Packit a4aae4
Packit a4aae4
 When reading data out of a variable that has been constrained, this method
Packit a4aae4
 assumes the N values/bytes of constrained data start at the beginning
Packit a4aae4
 of the object's internal buffer. For example, do not load an entire
Packit a4aae4
 Vector's data using val2buf(), constrain and then use this method to
Packit a4aae4
 get the data. Unless your constraint starts with the [0]th element, the
Packit a4aae4
 result will not be the correct values.
Packit a4aae4
Packit a4aae4
 In the case of a Vector of Str objects, this method will return an array
Packit a4aae4
 of C++ std::string objects.
Packit a4aae4
Packit a4aae4
 @note It's best to define the pointer to reference the data as
Packit a4aae4
 'char *data' and then call this method using '..->buf2val((void**)&data)'.
Packit a4aae4
 Then free the storage once you're done using 'delete[] data'. It's not
Packit a4aae4
 correct C++ to use 'delete[]' on a void pointer and the allocated memory
Packit a4aae4
 \e is an array of char, so 'delete[]' is needed.
Packit a4aae4
Packit a4aae4
 @return The number of bytes used to store the array.
Packit a4aae4
 @param val A pointer to a pointer to the memory into which the
Packit a4aae4
 class data will be copied.  If the value pointed to is NULL,
Packit a4aae4
 memory will be allocated to hold the data, and the pointer value
Packit a4aae4
 modified accordingly.  The calling program is responsible for
Packit a4aae4
 deallocating the memory indicated by this pointer.
Packit a4aae4
 @exception InternalErr Thrown if \e val is null.
Packit a4aae4
 @see Vector::set_vec */
Packit a4aae4
unsigned int Vector::buf2val(void **val)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // The same comment in Vector::val2buf applies here!
Packit a4aae4
    if (!val)
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
Packit a4aae4
Packit a4aae4
    unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
Packit a4aae4
Packit a4aae4
    // This is the width computed using length(). The
Packit a4aae4
    // length() property is changed when a projection
Packit a4aae4
    // constraint is applied. Thus this is the number of
Packit a4aae4
    // bytes in the buffer given the current constraint.
Packit a4aae4
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            if (!d_buf)
Packit a4aae4
                throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
Packit a4aae4
            if (!*val)
Packit a4aae4
                *val = new char[wid];
Packit a4aae4
Packit a4aae4
            memcpy(*val, d_buf, wid);
Packit a4aae4
            return wid;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c: {
Packit a4aae4
        	if (d_str.empty())
Packit a4aae4
        		throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
Packit a4aae4
            if (!*val)
Packit a4aae4
                *val = new string[d_length];
Packit a4aae4
Packit a4aae4
            for (int i = 0; i < d_length; ++i)
Packit a4aae4
                *(static_cast<string *> (*val) + i) = d_str[i];
Packit a4aae4
Packit a4aae4
            return width();
Packit a4aae4
            break;
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    //return wid;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Sets an element of the vector to a given value.  If the type of
Packit a4aae4
 the input and the type of the Vector do not match, an error
Packit a4aae4
 condition is returned.
Packit a4aae4
Packit a4aae4
 Use this function only with Vectors containing compound
Packit a4aae4
 types.  See \c buf2val() or the \c set_value() methods to access
Packit a4aae4
 members of Vector containing simple types.
Packit a4aae4
Packit a4aae4
 @note This method copies \e val; the caller is responsible for deleting
Packit a4aae4
 instance passed as the actual parameter.
Packit a4aae4
Packit a4aae4
 @brief Sets element i to value val.
Packit a4aae4
 @return void
Packit a4aae4
 @exception InternalErr Thrown if \e i is out of range, \e val is null or
Packit a4aae4
 there was a type mismatch between the BaseType referenced by \e val and
Packit a4aae4
 the \e ith element of this Vector.
Packit a4aae4
 @param i The index of the element to be changed.
Packit a4aae4
 @param val A pointer to the value to be inserted into the
Packit a4aae4
 array.
Packit a4aae4
 @see Vector::buf2val */
Packit a4aae4
void Vector::set_vec(unsigned int i, BaseType * val)
Packit a4aae4
{
Packit a4aae4
	Vector::set_vec_nocopy(i, val->ptr_duplicate());
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * @brief Sets element i to value val.
Packit a4aae4
 * Set the ith element to val. Extend the vector if needed.
Packit a4aae4
 *
Packit a4aae4
 * @note It is best to call vec_resize() first and allocate enough elements
Packit a4aae4
 * before calling this method.
Packit a4aae4
 *
Packit a4aae4
 * @note This method does not copy \e val; this class will free the instance
Packit a4aae4
 * when the variable is deleted or when clear_local_data() is called.
Packit a4aae4
 * @see Vector::set_vec()
Packit a4aae4
 * */
Packit a4aae4
void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
Packit a4aae4
{
Packit a4aae4
    // Jose Garcia
Packit a4aae4
    // This is a public method which allows users to set the elements
Packit a4aae4
    // of *this* vector. Passing an invalid index, a NULL pointer or
Packit a4aae4
    // mismatching the vector type are internal errors.
Packit a4aae4
    if (i >= static_cast<unsigned int> (d_length))
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
Packit a4aae4
    if (!val)
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
Packit a4aae4
    if (val->type() != d_proto->type())
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
Packit a4aae4
Packit a4aae4
    // This code originally used capacity() instead of size(), but that was an error.
Packit a4aae4
    // Use capacity() when using reserve() and size() when using resize(). Mixing
Packit a4aae4
    // capacity() with resize() leaves holes in the data, where (pointer) values are
Packit a4aae4
    // filled with nulls during successive calls to resize(). The resize() heuristic
Packit a4aae4
    // remembers previous calls on a given vector<> and allocates larger than requested
Packit a4aae4
    // blocks of memory on successive calls, which has the strange affect of erasing
Packit a4aae4
    // values already in the vector in the parts just added.
Packit a4aae4
    // jhrg 5/18/17
Packit a4aae4
    if (i >= d_compound_buf.size()) {
Packit a4aae4
        vec_resize(d_compound_buf.size() + 100);
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    d_compound_buf[i] = val;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Remove any read or set data in the private data of this Vector,
Packit a4aae4
 * setting read_p() to false.
Packit a4aae4
 * Essentially clears the _buf, d_str, and d_compound_buf of any data.
Packit a4aae4
 * Useful for tightening up memory when the data is no longer needed,
Packit a4aae4
 * but the object cannot yet be destroyed.
Packit a4aae4
 *
Packit a4aae4
 * On exit: get_value_capacity() == 0 && !read_p()
Packit a4aae4
 */
Packit a4aae4
void Vector::clear_local_data()
Packit a4aae4
{
Packit a4aae4
    if (d_buf) {
Packit a4aae4
        delete[] d_buf;
Packit a4aae4
        d_buf = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
Packit a4aae4
        delete d_compound_buf[i];
Packit a4aae4
        d_compound_buf[i] = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // Force memory to be reclaimed.
Packit a4aae4
    d_compound_buf.resize(0);
Packit a4aae4
    d_str.resize(0);
Packit a4aae4
Packit a4aae4
    d_capacity = 0;
Packit a4aae4
    set_read_p(false);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Return the capacity of the Vector in terms of number of
Packit a4aae4
 * elements of its data type that it can currently hold (i.e. not bytes).
Packit a4aae4
 * For example, this could be
Packit a4aae4
 * the size of the _buf array in bytes / sizeof(T) for the cardinal
Packit a4aae4
 * types T, or the capacity of the d_str vector if T is string or url type.
Packit a4aae4
 */
Packit a4aae4
unsigned int Vector::get_value_capacity() const
Packit a4aae4
{
Packit a4aae4
    return d_capacity;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Allocate enough memory for the Vector to contain
Packit a4aae4
 * numElements data elements of the Vector's type.
Packit a4aae4
 * Must be used before set_value_slice_from_row_major_vector
Packit a4aae4
 * to ensure memory exists.
Packit a4aae4
 * @param numElements  the number of elements of the Vector's type
Packit a4aae4
 *                     to preallocate storage for.
Packit a4aae4
 * @exception if the memory cannot be allocated
Packit a4aae4
 */
Packit a4aae4
void Vector::reserve_value_capacity(unsigned int numElements)
Packit a4aae4
{
Packit a4aae4
    if (!d_proto) {
Packit a4aae4
        throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
Packit a4aae4
    }
Packit a4aae4
    switch (d_proto->type()) {
Packit a4aae4
        case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
        case dods_int8_c:
Packit a4aae4
        case dods_uint8_c:
Packit a4aae4
        case dods_int16_c:
Packit a4aae4
        case dods_uint16_c:
Packit a4aae4
        case dods_int32_c:
Packit a4aae4
        case dods_uint32_c:
Packit a4aae4
        case dods_int64_c:
Packit a4aae4
        case dods_uint64_c:
Packit a4aae4
Packit a4aae4
        case dods_enum_c:
Packit a4aae4
Packit a4aae4
        case dods_float32_c:
Packit a4aae4
        case dods_float64_c:
Packit a4aae4
            // Make _buf be the right size and set _capacity
Packit a4aae4
            m_create_cardinal_data_buffer_for_type(numElements);
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_str_c:
Packit a4aae4
        case dods_url_c:
Packit a4aae4
            // Make sure the d_str has enough room for all the strings.
Packit a4aae4
            // Technically not needed, but it will speed things up for large arrays.
Packit a4aae4
            d_str.reserve(numElements);
Packit a4aae4
            d_capacity = numElements;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_array_c:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
        case dods_structure_c:
Packit a4aae4
        case dods_sequence_c:
Packit a4aae4
        case dods_grid_c:
Packit a4aae4
            // not clear anyone will go this path, but best to be complete.
Packit a4aae4
            d_compound_buf.reserve(numElements);
Packit a4aae4
            d_capacity = numElements;
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
        default:
Packit a4aae4
            throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
Packit a4aae4
            break;
Packit a4aae4
Packit a4aae4
    } // switch
Packit a4aae4
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Make sure there's storage allocated for the current length()
Packit a4aae4
 * of the Vector.
Packit a4aae4
 * Same as reserveValueCapacity(length())
Packit a4aae4
 */
Packit a4aae4
void Vector::reserve_value_capacity()
Packit a4aae4
{
Packit a4aae4
    // Use the current length of the vector as the reserve amount.
Packit a4aae4
    reserve_value_capacity(length());
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Copy rowMajorData.length() elements currently in a rowMajorData buffer
Packit a4aae4
 * into this value buffer starting at element index startElement and
Packit a4aae4
 * continuing up to startElement+rowMajorData.length()-1
Packit a4aae4
 *
Packit a4aae4
 * This is used for aggregating together smaller rowMajor vectors
Packit a4aae4
 * into a larger one.
Packit a4aae4
 *
Packit a4aae4
 * Note: unlike the other set_value calls, this does NOT set read_p()
Packit a4aae4
 *       since it is assumed to be used as a partial read and the caller
Packit a4aae4
 *       is expected to set_read_p() when the data is complete.
Packit a4aae4
 *
Packit a4aae4
 * ASSUMES: rowMajorData.read_p() so that the data is valid!
Packit a4aae4
 * ASSUMES: this Vector has enough value_capacity() to contain
Packit a4aae4
 *          all the elements such that:
Packit a4aae4
 *          startElement + rowMajorData.length()
Packit a4aae4
 *          <= this->value_capacity().
Packit a4aae4
 * ASSUMES: the data type of this->var() and rowMajorData.var()
Packit a4aae4
 *          MUST be non-NULL and be the same!
Packit a4aae4
 *
Packit a4aae4
 * @param rowMajorDataC the vector from which to copy data,
Packit a4aae4
 *                     assumed already read in or set.
Packit a4aae4
 * @param startElement the element index
Packit a4aae4
 *                     (NOT byte, but rather data type element)
Packit a4aae4
 *                     to place the first data value.
Packit a4aae4
 * @return the number of elements added, such that:
Packit a4aae4
 *         startElement + the return value is the next "free" element.
Packit a4aae4
 */
Packit a4aae4
unsigned int
Packit a4aae4
Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
Packit a4aae4
{
Packit a4aae4
	static const string funcName = "set_value_slice_from_row_major_vector:";
Packit a4aae4
Packit a4aae4
	// semantically const from the caller's viewpoint, but some calls are not syntactic const.
Packit a4aae4
	Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
Packit a4aae4
Packit a4aae4
	bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
Packit a4aae4
	if (!typesMatch) {
Packit a4aae4
		throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	// Make sure the data exists
Packit a4aae4
	if (!rowMajorData.read_p()) {
Packit a4aae4
		throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
				funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	// Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
Packit a4aae4
	if (rowMajorData.length() < 0) {
Packit a4aae4
		throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
				funcName
Packit a4aae4
						+ "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	// The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
Packit a4aae4
	// I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
Packit a4aae4
	if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
Packit a4aae4
		throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
				funcName
Packit a4aae4
						+ "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	// Make sure there's enough room in this Vector to store all the elements requested.  Again,
Packit a4aae4
	// better to throw than just copy what we can since it implies a logic error that needs to be solved.
Packit a4aae4
	if (d_capacity < (startElement + rowMajorData.length())) {
Packit a4aae4
		throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
				funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
Packit a4aae4
	}
Packit a4aae4
Packit a4aae4
	// OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
Packit a4aae4
	switch (d_proto->type()) {
Packit a4aae4
		case dods_int8_c:
Packit a4aae4
		case dods_uint8_c:
Packit a4aae4
		case dods_byte_c:
Packit a4aae4
        case dods_char_c:
Packit a4aae4
		case dods_int16_c:
Packit a4aae4
		case dods_uint16_c:
Packit a4aae4
		case dods_int32_c:
Packit a4aae4
		case dods_uint32_c:
Packit a4aae4
		case dods_int64_c:
Packit a4aae4
		case dods_uint64_c:
Packit a4aae4
Packit a4aae4
		case dods_enum_c:
Packit a4aae4
Packit a4aae4
		case dods_float32_c:
Packit a4aae4
		case dods_float64_c: {
Packit a4aae4
			if (!d_buf) {
Packit a4aae4
				throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
Packit a4aae4
			}
Packit a4aae4
			if (!rowMajorData.d_buf) {
Packit a4aae4
				throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
Packit a4aae4
			}
Packit a4aae4
			// memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
Packit a4aae4
			int varWidth = d_proto->width();
Packit a4aae4
			char* pFromBuf = rowMajorData.d_buf;
Packit a4aae4
			int numBytesToCopy = rowMajorData.width(true);
Packit a4aae4
			char* pIntoBuf = d_buf + (startElement * varWidth);
Packit a4aae4
			memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
Packit a4aae4
			break;
Packit a4aae4
		}
Packit a4aae4
Packit a4aae4
		case dods_str_c:
Packit a4aae4
		case dods_url_c:
Packit a4aae4
			// Strings need to be copied directly
Packit a4aae4
			for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
Packit a4aae4
				d_str[startElement + i] = rowMajorData.d_str[i];
Packit a4aae4
			}
Packit a4aae4
			break;
Packit a4aae4
Packit a4aae4
		case dods_array_c:
Packit a4aae4
        case dods_opaque_c:
Packit a4aae4
		case dods_structure_c:
Packit a4aae4
		case dods_sequence_c:
Packit a4aae4
		case dods_grid_c:
Packit a4aae4
			// Not sure that this function will be used for these type of nested objects, so I will throw here.
Packit a4aae4
			throw InternalErr(__FILE__, __LINE__,
Packit a4aae4
					funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
Packit a4aae4
			break;
Packit a4aae4
Packit a4aae4
		default:
Packit a4aae4
			throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
Packit a4aae4
			break;
Packit a4aae4
Packit a4aae4
	} // switch (_var->type())
Packit a4aae4
Packit a4aae4
	// This is how many elements we copied.
Packit a4aae4
	return (unsigned int) rowMajorData.length();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/**
Packit a4aae4
 * Does the C++ type correspond to the DAP Type enum value? This works only for
Packit a4aae4
 * numeric cardinal types. For Enums, pass the value of element_type(); for all
Packit a4aae4
 * others use type().
Packit a4aae4
 * @param t
Packit a4aae4
 * @param dt
Packit a4aae4
 * @return True if the types match, false otherwise
Packit a4aae4
 */
Packit a4aae4
template <typename T>
Packit a4aae4
static bool types_match(Type t, T *cpp_var)
Packit a4aae4
{
Packit a4aae4
    switch (t) {
Packit a4aae4
    case dods_byte_c:
Packit a4aae4
    case dods_char_c:
Packit a4aae4
    case dods_uint8_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_byte*);
Packit a4aae4
Packit a4aae4
    case dods_int8_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_int8*);
Packit a4aae4
    case dods_int16_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_int16*);
Packit a4aae4
    case dods_uint16_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_uint16*);
Packit a4aae4
    case dods_int32_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_int32*);
Packit a4aae4
    case dods_uint32_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_uint32*);
Packit a4aae4
    case dods_int64_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_int64*);
Packit a4aae4
    case dods_uint64_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_uint64*);
Packit a4aae4
Packit a4aae4
    case dods_float32_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_float32*);
Packit a4aae4
    case dods_float64_c:
Packit a4aae4
        return typeid(cpp_var) == typeid(dods_float64*);
Packit a4aae4
Packit a4aae4
    case dods_null_c:
Packit a4aae4
    case dods_enum_c:
Packit a4aae4
    case dods_str_c:
Packit a4aae4
    case dods_url_c:
Packit a4aae4
    case dods_opaque_c:
Packit a4aae4
    case dods_array_c:
Packit a4aae4
    case dods_structure_c:
Packit a4aae4
    case dods_sequence_c:
Packit a4aae4
    case dods_group_c:
Packit a4aae4
    default:
Packit a4aae4
        return false;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
//@{
Packit a4aae4
/** @brief set the value of a byte array */
Packit a4aae4
Packit a4aae4
template <typename T>
Packit a4aae4
bool Vector::set_value_worker(T *v, int sz)
Packit a4aae4
{
Packit a4aae4
    if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
Packit a4aae4
        return false;
Packit a4aae4
Packit a4aae4
    m_set_cardinal_values_internal(v, sz);
Packit a4aae4
    return true;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool Vector::set_value(dods_byte *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_int8 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_int16 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_uint16 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_int32 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_uint32 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_int64 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_uint64 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_float32 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(dods_float64 *val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** @brief set the value of a string or url array */
Packit a4aae4
bool Vector::set_value(string *val, int sz)
Packit a4aae4
{
Packit a4aae4
    if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
Packit a4aae4
        d_str.resize(sz);
Packit a4aae4
        d_capacity = sz;
Packit a4aae4
        for (register int t = 0; t < sz; t++) {
Packit a4aae4
            d_str[t] = val[t];
Packit a4aae4
        }
Packit a4aae4
        set_length(sz);
Packit a4aae4
        set_read_p(true);
Packit a4aae4
        return true;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        return false;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
template<typename T>
Packit a4aae4
bool Vector::set_value_worker(vector<T> &v, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value(&v[0], sz);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool Vector::set_value(vector<dods_byte> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_int8> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_int16> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_uint16> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_int32> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_uint32> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_int64> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_uint64> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_float32> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
bool Vector::set_value(vector<dods_float64> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    return set_value_worker(val, sz);
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** @brief set the value of a string or url array */
Packit a4aae4
bool Vector::set_value(vector<string> &val, int sz)
Packit a4aae4
{
Packit a4aae4
    if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
Packit a4aae4
        d_str.resize(sz);
Packit a4aae4
        d_capacity = sz;
Packit a4aae4
        for (register int t = 0; t < sz; t++) {
Packit a4aae4
            d_str[t] = val[t];
Packit a4aae4
        }
Packit a4aae4
        set_length(sz);
Packit a4aae4
        set_read_p(true);
Packit a4aae4
        return true;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        return false;
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
//@}
Packit a4aae4
Packit a4aae4
//@{
Packit a4aae4
Packit a4aae4
/** @brief Get a copy of the data held by this variable using the passed subsetIndex
Packit a4aae4
 * vector to identify which values to return.
Packit a4aae4
 *
Packit a4aae4
 * Read data from this variable's internal storage using the passed std::vector
Packit a4aae4
 * as an sub-setting index to the values to be returned. For example, if \c subsetIndex
Packit a4aae4
 * contains 1,3,5,7 and 9, then 'b' will contain the five values found at indexes
Packit a4aae4
 * 1,3, ..., 9.
Packit a4aae4
 *
Packit a4aae4
 * @note The memory referenced by \c b must point to enough memory to hold index.size()
Packit a4aae4
 * bytes; no test for this is performed.
Packit a4aae4
 * @note This can only be called for cardinal types.
Packit a4aae4
 *
Packit a4aae4
 * @param index A std::vector<long> where each value in the vector is the
Packit a4aae4
 * location in the Vector's internal storage from which to read the returned value.
Packit a4aae4
 * @param b A pointer to the memory to hold the data; must be at least
Packit a4aae4
 * length() * sizeof(dods_byte) in size.*/
Packit a4aae4
template <typename T>
Packit a4aae4
void Vector::value_worker(vector<unsigned int> *indices, T *b) const
Packit a4aae4
{
Packit a4aae4
   // unsigned long currentIndex;
Packit a4aae4
#if 0
Packit a4aae4
    // Iterator version. Not tested, jhrg 8/14/13
Packit a4aae4
    for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
Packit a4aae4
        unsigned long currentIndex = *i;
Packit a4aae4
        if(currentIndex > (unsigned int)length()){
Packit a4aae4
            stringstream s;
Packit a4aae4
            s << "Vector::value() - Subset index[" << i - subsetIndex->begin() <<  "] = " << currentIndex << " references a value that is " <<
Packit a4aae4
                    "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
Packit a4aae4
            throw Error(s.str());
Packit a4aae4
        }
Packit a4aae4
        b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
Packit a4aae4
    }
Packit a4aae4
#endif
Packit a4aae4
    for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
Packit a4aae4
        unsigned long currentIndex = (*indices)[i];
Packit a4aae4
        if (currentIndex > (unsigned int)length()) {
Packit a4aae4
            stringstream s;
Packit a4aae4
            s << "Vector::value() - Subset index[" << i <<  "] = " << currentIndex << " references a value that is " <<
Packit a4aae4
                    "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
Packit a4aae4
            throw Error(s.str());
Packit a4aae4
        }
Packit a4aae4
        b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_byte *b) const    { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const    { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const   { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const  { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const   { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const  { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const   { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const  { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
Packit a4aae4
void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
Packit a4aae4
template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
/** @brief Get a copy of the data held by this variable using the passed subsetIndex vector to identify which values to return. **/
Packit a4aae4
void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
Packit a4aae4
{
Packit a4aae4
    unsigned long currentIndex;
Packit a4aae4
Packit a4aae4
    if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
Packit a4aae4
        for(unsigned long i=0; i<subsetIndex->size() ;++i){
Packit a4aae4
            currentIndex = (*subsetIndex)[i] ;
Packit a4aae4
            if(currentIndex > (unsigned int)length()){
Packit a4aae4
                stringstream s;
Packit a4aae4
                s << "Vector::value() - Subset index[" << i <<  "] = " << currentIndex << " references a value that is " <<
Packit a4aae4
                        "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
Packit a4aae4
                throw Error(s.str());
Packit a4aae4
            }
Packit a4aae4
            b[i] = d_str[currentIndex];
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
template <typename T>
Packit a4aae4
void Vector::value_worker(T *v) const
Packit a4aae4
{
Packit a4aae4
    // Only copy if v is not null and the proto's  type matches.
Packit a4aae4
    // For Enums, use the element type since type == dods_enum_c.
Packit a4aae4
    if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
Packit a4aae4
        memcpy(v, d_buf, length() * sizeof(T));
Packit a4aae4
}
Packit a4aae4
void Vector::value(dods_byte *b) const    { value_worker(b); }
Packit a4aae4
void Vector::value(dods_int8 *b) const    { value_worker(b); }
Packit a4aae4
void Vector::value(dods_int16 *b) const   { value_worker(b); }
Packit a4aae4
void Vector::value(dods_uint16 *b) const  { value_worker(b); }
Packit a4aae4
void Vector::value(dods_int32 *b) const   { value_worker(b); }
Packit a4aae4
void Vector::value(dods_uint32 *b) const  { value_worker(b); }
Packit a4aae4
void Vector::value(dods_int64 *b) const   { value_worker(b); }
Packit a4aae4
void Vector::value(dods_uint64 *b) const  { value_worker(b); }
Packit a4aae4
void Vector::value(dods_float32 *b) const { value_worker(b); }
Packit a4aae4
void Vector::value(dods_float64 *b) const { value_worker(b); }
Packit a4aae4
Packit a4aae4
#if 0
Packit a4aae4
template void Vector::value(dods_byte *v) const;
Packit a4aae4
template void Vector::value(dods_int8 *v) const;
Packit a4aae4
template void Vector::value(dods_int16 *v) const;
Packit a4aae4
template void Vector::value(dods_uint16 *v) const;
Packit a4aae4
template void Vector::value(dods_int32 *v) const;
Packit a4aae4
template void Vector::value(dods_uint32 *v) const;
Packit a4aae4
template void Vector::value(dods_int64 *v) const;
Packit a4aae4
template void Vector::value(dods_uint64 *v) const;
Packit a4aae4
template void Vector::value(dods_float32 *v) const;
Packit a4aae4
template void Vector::value(dods_float64 *v) const;
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
Packit a4aae4
/** @brief Get a copy of the data held by this variable. */
Packit a4aae4
void Vector::value(vector<string> &b) const
Packit a4aae4
{
Packit a4aae4
    if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
Packit a4aae4
        b = d_str;
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
/** Allocate memory and copy data into the new buffer. Return the new
Packit a4aae4
 buffer's pointer. The caller must delete the storage. */
Packit a4aae4
void *Vector::value()
Packit a4aae4
{
Packit a4aae4
    void *buffer = new char[width(true)];
Packit a4aae4
Packit a4aae4
    memcpy(buffer, d_buf, width(true));
Packit a4aae4
Packit a4aae4
    return buffer;
Packit a4aae4
}
Packit a4aae4
//@}
Packit a4aae4
Packit a4aae4
/** @brief Add the BaseType pointer to this constructor type
Packit a4aae4
 instance.
Packit a4aae4
Packit a4aae4
 Propagate the name of the BaseType instance to this instance. This
Packit a4aae4
 ensures that variables at any given level of the DDS table have
Packit a4aae4
 unique names (i.e., that Arrays do not have their default name ""). If
Packit a4aae4
 <tt>v</tt>'s name is null, then assume that the array \e is named and
Packit a4aae4
 don't overwrite it with <tt>v</tt>'s null name.
Packit a4aae4
Packit a4aae4
 @note As is the case with Array, this method can be called with a null
Packit a4aae4
 BaseType pointer.
Packit a4aae4
Packit a4aae4
 @param v The template variable for the array
Packit a4aae4
 @param p The Part parameter defaults to nil and is ignored by this method.
Packit a4aae4
 */
Packit a4aae4
void Vector::add_var(BaseType * v, Part /*p*/)
Packit a4aae4
{
Packit a4aae4
#if 0
Packit a4aae4
	// Why doesn't this work?  tried all 3 variants. jhrg 8/14/13
Packit a4aae4
	Vector::add_var_nocopy(v->ptr_duplicate(), p);
Packit a4aae4
	add_var_nocopy(v->ptr_duplicate(), p);
Packit a4aae4
	add_var_nocopy(v->ptr_duplicate());
Packit a4aae4
#else
Packit a4aae4
	// Delete the current template variable
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        delete d_proto;
Packit a4aae4
        d_proto = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // if 'v' is null, just set _var to null and exit.
Packit a4aae4
    if (!v) {
Packit a4aae4
        d_proto = 0;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        // Jose Garcia
Packit a4aae4
        // By getting a copy of this object to be assigned to _var
Packit a4aae4
        // we let the owner of 'v' to deallocate it as necessary.
Packit a4aae4
        d_proto = v->ptr_duplicate();
Packit a4aae4
Packit a4aae4
        // If 'v' has a name, use it as the name of the array. If v doesn't have
Packit a4aae4
        // a name, then make sure to copy the array's name to it
Packit a4aae4
        // so that software which uses the template's name will still work.
Packit a4aae4
        if (!v->name().empty())
Packit a4aae4
            set_name(v->name());
Packit a4aae4
        else
Packit a4aae4
            d_proto->set_name(name());
Packit a4aae4
Packit a4aae4
        d_proto->set_parent(this); // Vector --> child
Packit a4aae4
Packit a4aae4
        DBG(cerr << "Vector::add_var: Added variable " << v << " ("
Packit a4aae4
                << v->name() << " " << v->type_name() << ")" << endl);
Packit a4aae4
    }
Packit a4aae4
#endif
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
void Vector::add_var_nocopy(BaseType * v, Part)
Packit a4aae4
{
Packit a4aae4
	// Delete the current template variable
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        delete d_proto;
Packit a4aae4
        d_proto = 0;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    // if 'v' is null, just set _var to null and exit.
Packit a4aae4
    if (!v) {
Packit a4aae4
        d_proto = 0;
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        d_proto = v;
Packit a4aae4
Packit a4aae4
        // If 'v' has a name, use it as the name of the array. If it *is*
Packit a4aae4
        // empty, then make sure to copy the array's name to the template
Packit a4aae4
        // so that software which uses the template's name will still work.
Packit a4aae4
        if (!v->name().empty())
Packit a4aae4
            set_name(v->name());
Packit a4aae4
        else
Packit a4aae4
            d_proto->set_name(name());
Packit a4aae4
Packit a4aae4
        d_proto->set_parent(this); // Vector is the parent; proto is the child
Packit a4aae4
Packit a4aae4
        DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
Packit a4aae4
                << v->name() << " " << v->type_name() << ")" << endl);
Packit a4aae4
    }
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
bool Vector::check_semantics(string & msg, bool)
Packit a4aae4
{
Packit a4aae4
    return BaseType::check_semantics(msg);
Packit a4aae4
}
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 Vector::dump(ostream &strm) const
Packit a4aae4
{
Packit a4aae4
    strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
Packit a4aae4
    DapIndent::Indent();
Packit a4aae4
    BaseType::dump(strm);
Packit a4aae4
    strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
Packit a4aae4
    if (d_proto) {
Packit a4aae4
        strm << DapIndent::LMarg << "base type:" << endl;
Packit a4aae4
        DapIndent::Indent();
Packit a4aae4
        d_proto->dump(strm);
Packit a4aae4
        DapIndent::UnIndent();
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        strm << DapIndent::LMarg << "base type: not set" << endl;
Packit a4aae4
    }
Packit a4aae4
    strm << DapIndent::LMarg << "vector contents:" << endl;
Packit a4aae4
    DapIndent::Indent();
Packit a4aae4
    for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
Packit a4aae4
        if (d_compound_buf[i])
Packit a4aae4
            d_compound_buf[i]->dump(strm);
Packit a4aae4
        else
Packit a4aae4
            strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
Packit a4aae4
    }
Packit a4aae4
    DapIndent::UnIndent();
Packit a4aae4
    strm << DapIndent::LMarg << "strings:" << endl;
Packit a4aae4
    DapIndent::Indent();
Packit a4aae4
    for (unsigned i = 0; i < d_str.size(); i++) {
Packit a4aae4
        strm << DapIndent::LMarg << d_str[i] << endl;
Packit a4aae4
    }
Packit a4aae4
    DapIndent::UnIndent();
Packit a4aae4
    if (d_buf) {
Packit a4aae4
        switch (d_proto != 0 ? d_proto->type() : 0) {
Packit a4aae4
            case dods_byte_c:
Packit a4aae4
            case dods_char_c:
Packit a4aae4
                strm << DapIndent::LMarg << "_buf: ";
Packit a4aae4
                strm.write(d_buf, d_length);
Packit a4aae4
                strm << endl;
Packit a4aae4
                break;
Packit a4aae4
Packit a4aae4
            case 0:
Packit a4aae4
            default:
Packit a4aae4
                strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
Packit a4aae4
                break;
Packit a4aae4
        }
Packit a4aae4
    }
Packit a4aae4
    else {
Packit a4aae4
        strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    DapIndent::UnIndent();
Packit a4aae4
}
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4