1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
// -*- mode: c++; c-basic-offset:4 -*-
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.
// Copyright (c) 2013 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
#include "config.h"
#include "D4Group.h"
#include "D4EnumDefs.h"
#include <sstream>
#include "dods-limits.h"
#include "util.h"
namespace libdap {
/** Test if a particular value is legal for a given type. In a D4EnumDef,
* all values are actually stored in a long long, but the different
* enumerations can specify different types like Byte, Int32, ..., and this
* method is used to test that the values match those types.
*/
bool
D4EnumDef::is_valid_enum_value(long long value)
{
switch (type()) {
case dods_int8_c:
return (value >= DODS_SCHAR_MIN && value <= DODS_SCHAR_MAX);
case dods_byte_c:
case dods_uint8_c:
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_UCHAR_MAX);
case dods_int16_c:
return (value >= DODS_SHRT_MIN && value <= DODS_SHRT_MAX);
case dods_uint16_c:
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_USHRT_MAX);
case dods_int32_c:
return (value >= DODS_INT_MIN && value <= DODS_INT_MAX);
case dods_uint32_c:
return (value >= 0 && static_cast<unsigned long long>(value) <= DODS_UINT_MAX);
case dods_int64_c:
return true; // This is always true: (value >= DODS_LLONG_MIN && value <= DODS_LLONG_MAX);
case dods_uint64_c:
return (value >= 0 /*Always true: && static_cast<unsigned long long>(value) <= DODS_ULLONG_MAX*/);
default:
return false;
}
}
#if 0
// Note that in order for this to work the second argument must not be a reference.
// jhrg 8/20/13
static bool
enum_def_name_eq(D4EnumDef *d, const string name)
{
return d->name() == name;
}
#endif
D4EnumDef *
D4EnumDefs::find_enum_def(const string &name)
{
auto d = find_if(d_enums.begin(), d_enums.end(),
[name](const D4EnumDef *def) { return name == def->name(); });
return (d != d_enums.end()) ? *d: nullptr;
}
void D4EnumDef::print_value(XMLWriter &xml, const D4EnumDef::tuple &tuple) const
{
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"EnumConst") < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write EnumConst element");
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)tuple.label.c_str()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
ostringstream oss;
oss << tuple.value;
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "value", (const xmlChar*)oss.str().c_str()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for value");
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not end EnumConst element");
}
void D4EnumDef::print_dap4(XMLWriter &xml) const
{
vector<D4EnumDef::tuple>::const_iterator i = d_tuples.begin();
while(i != d_tuples.end()) {
print_value(xml, *i++);
}
}
void D4EnumDefs::m_print_enum(XMLWriter &xml, D4EnumDef *e) const
{
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*)"Enumeration") < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write Enumeration element");
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)e->name().c_str()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "basetype", (const xmlChar*)D4type_name(e->type()).c_str()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
// print each of e.values
e->print_dap4(xml);
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
throw InternalErr(__FILE__, __LINE__, "Could not end Enumeration element");
}
void D4EnumDefs::print_dap4(XMLWriter &xml, bool constrained) const
{
D4EnumDefCIter i = d_enums.begin();
while (i != d_enums.end()) {
if (!constrained || parent()->find_first_var_that_uses_enumeration(*i))
m_print_enum(xml, *i);
++i;
}
}
} /* namespace libdap */
|