|
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 |
|