|
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) 2013 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 "D4Group.h"
|
|
Packit |
a4aae4 |
#include "D4EnumDefs.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "dods-limits.h"
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Test if a particular value is legal for a given type. In a D4EnumDef,
|
|
Packit |
a4aae4 |
* all values are actually stored in a long long, but the different
|
|
Packit |
a4aae4 |
* enumerations can specify different types like Byte, Int32, ..., and this
|
|
Packit |
a4aae4 |
* method is used to test that the values match those types.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
bool
|
|
Packit |
a4aae4 |
D4EnumDef::is_valid_enum_value(long long value)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
switch (type()) {
|
|
Packit |
a4aae4 |
case dods_int8_c:
|
|
Packit |
a4aae4 |
return (value >= DODS_SCHAR_MIN && value <= DODS_SCHAR_MAX);
|
|
Packit |
a4aae4 |
case dods_byte_c:
|
|
Packit |
a4aae4 |
case dods_uint8_c:
|
|
Packit |
a4aae4 |
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_UCHAR_MAX);
|
|
Packit |
a4aae4 |
case dods_int16_c:
|
|
Packit |
a4aae4 |
return (value >= DODS_SHRT_MIN && value <= DODS_SHRT_MAX);
|
|
Packit |
a4aae4 |
case dods_uint16_c:
|
|
Packit |
a4aae4 |
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_USHRT_MAX);
|
|
Packit |
a4aae4 |
case dods_int32_c:
|
|
Packit |
a4aae4 |
return (value >= DODS_INT_MIN && value <= DODS_INT_MAX);
|
|
Packit |
a4aae4 |
case dods_uint32_c:
|
|
Packit |
a4aae4 |
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_UINT_MAX);
|
|
Packit |
a4aae4 |
case dods_int64_c:
|
|
Packit |
a4aae4 |
return true; // This is always true: (value >= DODS_LLONG_MIN && value <= DODS_LLONG_MAX);
|
|
Packit |
a4aae4 |
case dods_uint64_c:
|
|
Packit |
a4aae4 |
return (value >= 0 /*Always true: && static_cast<unsigned long long>(value) <= DODS_ULLONG_MAX*/);
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
return false;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Note that in order for this to work the second argument must not be a reference.
|
|
Packit |
a4aae4 |
// jhrg 8/20/13
|
|
Packit |
a4aae4 |
static bool
|
|
Packit |
a4aae4 |
enum_def_name_eq(D4EnumDef *d, const string name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d->name() == name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
D4EnumDef *
|
|
Packit |
a4aae4 |
D4EnumDefs::find_enum_def(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
D4EnumDefIter d = find_if(d_enums.begin(), d_enums.end(), bind2nd(ptr_fun(enum_def_name_eq), name));
|
|
Packit |
a4aae4 |
return (d != d_enums.end()) ? *d: 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4EnumDef::print_value(XMLWriter &xml, const D4EnumDef::tuple &tuple) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"EnumConst") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write EnumConst element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)tuple.label.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
oss << tuple.value;
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "value", (const xmlChar*)oss.str().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for value");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end EnumConst element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4EnumDef::print_dap4(XMLWriter &xml) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
vector<D4EnumDef::tuple>::const_iterator i = d_tuples.begin();
|
|
Packit |
a4aae4 |
while(i != d_tuples.end()) {
|
|
Packit |
a4aae4 |
print_value(xml, *i++);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4EnumDefs::m_print_enum(XMLWriter &xml, D4EnumDef *e) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Enumeration") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Enumeration element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)e->name().c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "basetype", (const xmlChar*)D4type_name(e->type()).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// print each of e.values
|
|
Packit |
a4aae4 |
e->print_dap4(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end Enumeration element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void D4EnumDefs::print_dap4(XMLWriter &xml, bool constrained) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
D4EnumDefCIter i = d_enums.begin();
|
|
Packit |
a4aae4 |
while (i != d_enums.end()) {
|
|
Packit |
a4aae4 |
if (!constrained || parent()->find_first_var_that_uses_enumeration(*i))
|
|
Packit |
a4aae4 |
m_print_enum(xml, *i);
|
|
Packit |
a4aae4 |
++i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} /* namespace libdap */
|