|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// -*- mode: c++; c-basic-offset:4 -*-
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
|
|
Packit |
a4aae4 |
// Access Protocol.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Copyright (c) 2014 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 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "BaseType.h"
|
|
Packit |
a4aae4 |
#include "Array.h"
|
|
Packit |
a4aae4 |
#include "Byte.h"
|
|
Packit |
a4aae4 |
#include "Int8.h"
|
|
Packit |
a4aae4 |
#include "UInt16.h"
|
|
Packit |
a4aae4 |
#include "Int16.h"
|
|
Packit |
a4aae4 |
#include "UInt32.h"
|
|
Packit |
a4aae4 |
#include "Int32.h"
|
|
Packit |
a4aae4 |
#include "UInt64.h"
|
|
Packit |
a4aae4 |
#include "Int64.h"
|
|
Packit |
a4aae4 |
#include "Float32.h"
|
|
Packit |
a4aae4 |
#include "Float64.h"
|
|
Packit |
a4aae4 |
#include "Str.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "D4RValue.h"
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "dods-datatypes.h"
|
|
Packit |
a4aae4 |
#include "dods-limits.h"
|
|
Packit |
a4aae4 |
#include "parser-util.h"
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using namespace std;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4RValueList::m_duplicate(const D4RValueList &src)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (std::vector<D4RValue *>::const_iterator i = src.d_rvalues.begin(), e = src.d_rvalues.end(); i != e; ++i) {
|
|
Packit |
a4aae4 |
D4RValue *rv = *i;
|
|
Packit |
a4aae4 |
d_rvalues.push_back(new D4RValue(*rv));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValueList::~D4RValueList()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (std::vector<D4RValue *>::iterator i = d_rvalues.begin(), e = d_rvalues.end(); i != e; ++i)
|
|
Packit |
a4aae4 |
delete *i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
D4RValue::m_duplicate(const D4RValue &src)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_value_kind = src.d_value_kind;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_variable = src.d_variable; // weak pointers
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_func = src.d_func;
|
|
Packit |
a4aae4 |
d_args = (src.d_args != 0) ? new D4RValueList(*src.d_args) : 0; // deep copy these
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_constant = (src.d_constant != 0) ? src.d_constant->ptr_duplicate() : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
template<typename T, class DAP_TYPE>
|
|
Packit |
a4aae4 |
static BaseType *
|
|
Packit |
a4aae4 |
build_constant_array(vector<T> &values, DAP_TYPE &dt)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Array *array = new Array("", &dt);
|
|
Packit |
a4aae4 |
array->append_dim(values.size());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// TODO Make set_value_nocopy() methods so that values' pointers can be copied
|
|
Packit |
a4aae4 |
// instead of allocating memory twice. jhrg 7/5/13
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array->set_value(values, values.size());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
array->set_read_p(true);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static unsigned long counter = 1;
|
|
Packit |
a4aae4 |
array->set_name(string("g") + long_to_string(counter++));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return array;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(unsigned long long ull) : d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
UInt64 *ui = new UInt64("constant");
|
|
Packit |
a4aae4 |
ui->set_value(ull);
|
|
Packit |
a4aae4 |
d_constant = ui;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(long long ll) : d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Int64 *i = new Int64("constant");
|
|
Packit |
a4aae4 |
i->set_value(ll);
|
|
Packit |
a4aae4 |
d_constant = i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(double r) : d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Float64 *f = new Float64("constant");
|
|
Packit |
a4aae4 |
f->set_value(r);
|
|
Packit |
a4aae4 |
d_constant = f;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::string cpps) : d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Str *s = new Str("constant");
|
|
Packit |
a4aae4 |
s->set_value(remove_quotes(cpps));
|
|
Packit |
a4aae4 |
d_constant = s;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_byte> &byte_args)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Byte b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_args, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_int8> &byte_int8)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Int8 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_int8, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_uint16> &byte_uint16)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
UInt16 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_uint16, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_int16> &byte_int16)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Int16 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_int16, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_uint32> &byte_uint32)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
UInt32 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_uint32, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_int32> &byte_int32)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Int32 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_int32, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_uint64> &byte_uint64)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
UInt64 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_uint64, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_int64> &byte_int64)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Int64 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_int64, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_float32> &byte_float32)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Float32 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_float32, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::D4RValue(std::vector<dods_float64> &byte_float64)
|
|
Packit |
a4aae4 |
: d_variable(0), d_func(0), d_args(0), d_constant(0), d_value_kind(constant)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Float64 b("");
|
|
Packit |
a4aae4 |
d_constant = build_constant_array(byte_float64, b);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4RValue::~D4RValue() {
|
|
Packit |
a4aae4 |
// d_variable and d_func are weak pointers; don't delete.
|
|
Packit |
a4aae4 |
delete d_args;
|
|
Packit |
a4aae4 |
delete d_constant;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Build an appropriate RValue
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Look at the value in the string parameter and build an appropriate
|
|
Packit |
a4aae4 |
* BaseType, use that as a constant and build an RValue. This can be used
|
|
Packit |
a4aae4 |
* by the DAP4 parser directly to build the constants in filter clauses.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param cpps The string argument read by the parser.
|
|
Packit |
a4aae4 |
* @return A D4RValue pointer.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
D4RValue *D4RValueFactory(std::string cpps)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// First check if the string is a uint64, ..., then convert it.
|
|
Packit |
a4aae4 |
// Since the check_* function use the strtoull() functions, no
|
|
Packit |
a4aae4 |
// need to test for errors when building the actual values.
|
|
Packit |
a4aae4 |
if (check_uint64(cpps.c_str())) {
|
|
Packit |
a4aae4 |
return new D4RValue(strtoull(cpps.c_str(), &ptr, 0));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (check_int64(cpps.c_str())) {
|
|
Packit |
a4aae4 |
return new D4RValue(strtoll(cpps.c_str(), &ptr, 0));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (check_float64(cpps.c_str())) {
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
return new D4RValue(w32strtod(cpps.c_str(), &ptr));
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
return new D4RValue(strtod(cpps.c_str(), &ptr));
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return new D4RValue(cpps);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Get the value for a RValue object
|
|
Packit |
a4aae4 |
* Return the BaseType * for a given RValue. For a dataset variable, read the
|
|
Packit |
a4aae4 |
* variable's value and, for a function, evaluate that function. Since read()
|
|
Packit |
a4aae4 |
* is called for a dataset variable each time this method is called, if the
|
|
Packit |
a4aae4 |
* variable is part of a Sequence, the next value in the sequence will be returned.
|
|
Packit |
a4aae4 |
* However, since this code also sets the read_p property after calling read(),
|
|
Packit |
a4aae4 |
* if the variable does not have a new value, read() will not be called (using the
|
|
Packit |
a4aae4 |
* read_p property, the read() method is called only when the variable has a new
|
|
Packit |
a4aae4 |
* value to be read.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @note Unlike the DAP2 functions, we have an easier-to-follow memory model for
|
|
Packit |
a4aae4 |
* function values. The values (BaseType*) returned by this method will be packaged
|
|
Packit |
a4aae4 |
* up in a RValueList and deleted when that list is deleted. Constant values and
|
|
Packit |
a4aae4 |
* function result values will be deleted at that time; variables will not. Thus
|
|
Packit |
a4aae4 |
* Server Functions should always allocate storage for their return values.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @todo Could move the operation that wraps a constant in a BaseType to this method
|
|
Packit |
a4aae4 |
* while providing other ways to access the value(s) (methods to determine if the
|
|
Packit |
a4aae4 |
* rvalue is a constant and what DAP type it is, e.g.). This would provide an optimization
|
|
Packit |
a4aae4 |
* for the filter evaluator which may access the values many times. We might also
|
|
Packit |
a4aae4 |
* modify the server side functions so they could access constant values more efficiently.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param dmr The DMR to pass to a function.
|
|
Packit |
a4aae4 |
* @return A BaseType* that holds the value.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4RValue::value(DMR &dmr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
switch (d_value_kind) {
|
|
Packit |
a4aae4 |
case basetype:
|
|
Packit |
a4aae4 |
d_variable->read();
|
|
Packit |
a4aae4 |
d_variable->set_read_p(true);
|
|
Packit |
a4aae4 |
return d_variable;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case function:
|
|
Packit |
a4aae4 |
return (*d_func)(d_args, dmr);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case constant:
|
|
Packit |
a4aae4 |
return d_constant;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Unknown rvalue type.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0; // nullptr; added return to quiet warning. jhrg 3/24/15
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @brief Get the value for a RValue object
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* This version of value() will not work for function RValues, but has the advantage that
|
|
Packit |
a4aae4 |
* it can be used more easily for the D4RValue objects built for, and stored in, D4Filter-
|
|
Packit |
a4aae4 |
* Clause instances.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @see D4RValue::value(DMR&)
|
|
Packit |
a4aae4 |
* @return The value wrapped in a BaseType*
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
BaseType *
|
|
Packit |
a4aae4 |
D4RValue::value()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
switch (d_value_kind) {
|
|
Packit |
a4aae4 |
case basetype:
|
|
Packit |
a4aae4 |
d_variable->read();
|
|
Packit |
a4aae4 |
d_variable->set_read_p(true);
|
|
Packit |
a4aae4 |
return d_variable;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case function:
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, "An expression that included a function call was used in a place where that won't work.");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case constant:
|
|
Packit |
a4aae4 |
return d_constant;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Unknown rvalue type.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0; // nullptr; added return to quiet warning. jhrg 3/24/15
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|