|
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) 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 |
// These functions are utility functions used by the various DAP parsers (the
|
|
Packit |
a4aae4 |
// DAS, DDS and constraint expression parsers).
|
|
Packit |
a4aae4 |
// jhrg 9/7/95
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cerrno>
|
|
Packit |
a4aae4 |
#include <cassert>
|
|
Packit |
a4aae4 |
#include <cstring>
|
|
Packit |
a4aae4 |
#include <cmath>
|
|
Packit |
a4aae4 |
#include <cstdlib>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We wrap VC++ 6.x strtod() to account for a short comming
|
|
Packit |
a4aae4 |
// in that function in regards to "NaN".
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
#include <limits>
|
|
Packit |
a4aae4 |
double w32strtod(const char *, char **);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "Error.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
#include "parser.h" // defines constants such as ID_MAX
|
|
Packit |
a4aae4 |
#include "dods-limits.h"
|
|
Packit |
a4aae4 |
#include "util.h" // Jose Garcia: for append_long_to_string.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
// VC++ 6.x strtod() doesn't recognize "NaN". Account for it
|
|
Packit |
a4aae4 |
// by wrapping it around a check for the Nan string. Use of
|
|
Packit |
a4aae4 |
// the product is obsolete as of 1/2007, but it is unknown if
|
|
Packit |
a4aae4 |
// the issue is still there in later releases of that product.
|
|
Packit |
a4aae4 |
// ROM - 01/2007
|
|
Packit |
a4aae4 |
double w32strtod(const char *val, char **ptr)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Convert the two char arrays to compare to strings.
|
|
Packit |
a4aae4 |
string *sval = new string(val);
|
|
Packit |
a4aae4 |
string *snan = new string("NaN");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If val doesn't contain "NaN|Nan|nan|etc", use strtod as
|
|
Packit |
a4aae4 |
// provided.
|
|
Packit |
a4aae4 |
if (stricmp(sval->c_str(), snan->c_str()) != 0)
|
|
Packit |
a4aae4 |
return (strtod(val, ptr));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// But if it does, return the bit pattern for Nan and point
|
|
Packit |
a4aae4 |
// the parsing ptr arg at the trailing '\0'.
|
|
Packit |
a4aae4 |
*ptr = (char *) val + strlen(val);
|
|
Packit |
a4aae4 |
return (std::numeric_limits < double >::quiet_NaN());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Deprecated, but still used by the HDF4 EOS server code.
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
parse_error(parser_arg * arg, const char *msg, const int line_num,
|
|
Packit |
a4aae4 |
const char *context)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Jose Garcia
|
|
Packit |
a4aae4 |
// This assert(s) is (are) only for developing purposes
|
|
Packit |
a4aae4 |
// For production servers remove it by compiling with NDEBUG
|
|
Packit |
a4aae4 |
assert(arg);
|
|
Packit |
a4aae4 |
assert(msg);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
arg->set_status(FALSE);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string oss = "";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (line_num != 0) {
|
|
Packit |
a4aae4 |
oss += "Error parsing the text on line ";
|
|
Packit |
a4aae4 |
append_long_to_string(line_num, 10, oss);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
oss += "Parse error.";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (context)
|
|
Packit |
a4aae4 |
oss += (string) " at or near: " + context + (string) "\n" + msg
|
|
Packit |
a4aae4 |
+ (string) "\n";
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
oss += (string) "\n" + msg + (string) "\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
arg->set_error(new Error(unknown_error, oss));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
parse_error(const char *msg, const int line_num, const char *context)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Jose Garcia
|
|
Packit |
a4aae4 |
// This assert(s) is (are) only for developing purposes
|
|
Packit |
a4aae4 |
// For production servers remove it by compiling with NDEBUG
|
|
Packit |
a4aae4 |
assert(msg);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string oss = "";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (line_num != 0) {
|
|
Packit |
a4aae4 |
oss += "Error parsing the text on line ";
|
|
Packit |
a4aae4 |
append_long_to_string(line_num, 10, oss);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
oss += "Parse error.";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (context)
|
|
Packit |
a4aae4 |
oss += (string) " at or near: " + context + (string) "\n" + msg
|
|
Packit |
a4aae4 |
+ (string) "\n";
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
oss += (string) "\n" + msg + (string) "\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
throw Error(malformed_expr, oss);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// context comes from the parser and will always be a char * unless the
|
|
Packit |
a4aae4 |
// parsers change dramatically.
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
parse_error(const string & msg, const int line_num, const char *context)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
parse_error(msg.c_str(), line_num, context);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void save_str(char *dst, const char *src, const int line_num)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (strlen(src) >= ID_MAX)
|
|
Packit |
a4aae4 |
parse_error(string("The word `") + string(src)
|
|
Packit |
a4aae4 |
+ string("' is too long (it should be no longer than ")
|
|
Packit |
a4aae4 |
+ long_to_string(ID_MAX) + string(")."), line_num);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
strncpy(dst, src, ID_MAX);
|
|
Packit |
a4aae4 |
dst[ID_MAX - 1] = '\0'; /* in case ... */
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void save_str(string & dst, const char *src, const int)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
dst = src;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool is_keyword(string id, const string & keyword)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
downcase(id);
|
|
Packit |
a4aae4 |
id = prune_spaces(id);
|
|
Packit |
a4aae4 |
DBG(cerr << "is_keyword: " << keyword << " = " << id << endl);
|
|
Packit |
a4aae4 |
return id == keyword;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Check to see if <tt>val</tt> is a valid byte value. If not,
|
|
Packit |
a4aae4 |
generate an error message using <tt>parser_error()</tt>. There are
|
|
Packit |
a4aae4 |
two versions of <tt>check_byte()</tt>, one which calls
|
|
Packit |
a4aae4 |
<tt>parser_error()</tt> and prints an error message to stderr an
|
|
Packit |
a4aae4 |
one which calls <tt>parser_error()</tt> and generates and Error
|
|
Packit |
a4aae4 |
object.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return Returns: TRUE (1) if val is a byte value, FALSE (0) otherwise.
|
|
Packit |
a4aae4 |
@brief Is the value a valid byte?
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
int check_byte(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
long v = strtol(val, &ptr, 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "v: " << v << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We're very liberal here with values. Anything that can fit into 8 bits
|
|
Packit |
a4aae4 |
// is allowed through. Clients will have to deal with the fact that the
|
|
Packit |
a4aae4 |
// ASCII representation for the value might need to be tweaked. This is
|
|
Packit |
a4aae4 |
// especially the case for Java clients where Byte datatypes are
|
|
Packit |
a4aae4 |
// signed. 3/20/2000 jhrg
|
|
Packit |
a4aae4 |
if ((v < 0 && v < DODS_SCHAR_MIN)
|
|
Packit |
a4aae4 |
|| (v > 0 && static_cast < unsigned long >(v) > DODS_UCHAR_MAX))
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This version of check_int will pass base 8, 10 and 16 numbers when they
|
|
Packit |
a4aae4 |
// use the ANSI standard for string representation of those number bases.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_int16(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
long v = strtol(val, &ptr, 0); // `0' --> use val to determine base
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// Don't use the constant from limits.h, use the ones in dods-limits.h
|
|
Packit |
a4aae4 |
if (v > DODS_SHRT_MAX || v < DODS_SHRT_MIN) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_uint16(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
unsigned long v = strtol(val, &ptr, 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (v > DODS_USHRT_MAX) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_int32(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
long v = strtol(val, &ptr, 0); // `0' --> use val to determine base
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We need to check errno since strtol return clamps on overflow so the
|
|
Packit |
a4aae4 |
// check against the DODS values below will always pass, even for out of
|
|
Packit |
a4aae4 |
// bounds values in the string. mjohnson 7/20/09
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// This could be combined with the above, or course, but I'm making it
|
|
Packit |
a4aae4 |
// separate to highlight the test. On 64-bit linux boxes 'long' may be
|
|
Packit |
a4aae4 |
// 64-bits and so 'v' can hold more than a DODS_INT32. jhrg 3/23/10
|
|
Packit |
a4aae4 |
else if (v > DODS_INT_MAX || v < DODS_INT_MIN) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_uint32(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Eat whitespace and check for an initial '-' sign...
|
|
Packit |
a4aae4 |
// strtoul allows an initial minus. mjohnson
|
|
Packit |
a4aae4 |
const char* c = val;
|
|
Packit |
a4aae4 |
while (c && isspace(*c)) {
|
|
Packit |
a4aae4 |
c++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (c && (*c == '-')) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
unsigned long v = strtoul(val, &ptr, 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// check overflow first, or the below check is invalid due to
|
|
Packit |
a4aae4 |
// clamping to the maximum value by strtoul
|
|
Packit |
a4aae4 |
// maybe consider using long long for these checks? mjohnson
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
// See above.
|
|
Packit |
a4aae4 |
else if (v > DODS_UINT_MAX) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_int64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
long long v = strtoll(val, &ptr, 0); // `0' --> use val to determine base
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We need to check errno since strtol return clamps on overflow so the
|
|
Packit |
a4aae4 |
// check against the DODS values below will always pass, even for out of
|
|
Packit |
a4aae4 |
// bounds values in the string. mjohnson 7/20/09
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// This could be combined with the above, or course, but I'm making it
|
|
Packit |
a4aae4 |
// separate to highlight the test. On 64-bit linux boxes 'long' may be
|
|
Packit |
a4aae4 |
// 64-bits and so 'v' can hold more than a DODS_INT32. jhrg 3/23/10
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Removed - Coverity says it can never be false. Makes sense. jhrg 5/10/16
|
|
Packit |
a4aae4 |
else if (v <= DODS_LLONG_MAX && v >= DODS_LLONG_MIN) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_uint64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Eat whitespace and check for an initial '-' sign...
|
|
Packit |
a4aae4 |
// strtoul allows an initial minus. mjohnson
|
|
Packit |
a4aae4 |
const char* c = val;
|
|
Packit |
a4aae4 |
while (c && isspace(*c)) {
|
|
Packit |
a4aae4 |
c++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (c && (*c == '-')) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
unsigned long long v = strtoull(val, &ptr, 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (v > DODS_ULLONG_MAX) { // 2^61
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return v;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Check first for system errors (like numbers so small they convert
|
|
Packit |
a4aae4 |
// (erroneously) to zero. Then make sure that the value is within
|
|
Packit |
a4aae4 |
// limits.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_float32(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0; // Clear previous value. Fix for the 64bit
|
|
Packit |
a4aae4 |
// IRIX from Rob Morris. 5/21/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
double v = w32strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
double v = strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "v: " << v << ", ptr: " << ptr
|
|
Packit |
a4aae4 |
<< ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (errno == ERANGE || (v == 0.0 && val == ptr) || *ptr != '\0')
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
|
|
Packit |
a4aae4 |
|| *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl);
|
|
Packit |
a4aae4 |
double abs_val = fabs(v);
|
|
Packit |
a4aae4 |
if (abs_val > DODS_FLT_MAX
|
|
Packit |
a4aae4 |
|| (abs_val != 0.0 && abs_val < DODS_FLT_MIN))
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_float64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "val: " << val << endl);
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0; // Clear previous value. 5/21/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
double v = w32strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
double v = strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "v: " << v << ", ptr: " << ptr
|
|
Packit |
a4aae4 |
<< ", errno: " << errno << ", val==ptr: " << (val == ptr) << endl);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (errno == ERANGE || (v == 0.0 && val == ptr) || *ptr != '\0')
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
if ((v == 0.0 && (val == ptr || errno == HUGE_VAL || errno == ERANGE))
|
|
Packit |
a4aae4 |
|| *ptr != '\0') {
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl);
|
|
Packit |
a4aae4 |
double abs_val = fabs(v);
|
|
Packit |
a4aae4 |
if (abs_val > DODS_DBL_MAX
|
|
Packit |
a4aae4 |
|| (abs_val != 0.0 && abs_val < DODS_DBL_MIN))
|
|
Packit |
a4aae4 |
return FALSE;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
long long get_int64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
long long v = strtoll(val, &ptr, 0); // `0' --> use val to determine base
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' contains extra characters.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// We need to check errno since strtol return clamps on overflow so the
|
|
Packit |
a4aae4 |
// check against the DODS values below will always pass, even for out of
|
|
Packit |
a4aae4 |
// bounds values in the string. mjohnson 7/20/09
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// This could be combined with the above, or course, but I'm making it
|
|
Packit |
a4aae4 |
// separate to highlight the test. On 64-bit linux boxes 'long' may be
|
|
Packit |
a4aae4 |
// 64-bits and so 'v' can hold more than a DODS_INT32. jhrg 3/23/10
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// Removed because coverity flags it as useless, which it is until we
|
|
Packit |
a4aae4 |
// have 128-bit ints... jhrg 5/9/16
|
|
Packit |
a4aae4 |
else if (v > DODS_LLONG_MAX || v < DODS_LLONG_MIN) {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return v;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned long long get_uint64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// Eat whitespace and check for an initial '-' sign...
|
|
Packit |
a4aae4 |
// strtoul allows an initial minus. mjohnson
|
|
Packit |
a4aae4 |
const char* c = val;
|
|
Packit |
a4aae4 |
while (c && isspace(*c)) {
|
|
Packit |
a4aae4 |
c++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (c && (*c == '-')) {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is not a valid array index.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0;
|
|
Packit |
a4aae4 |
unsigned long long v = strtoull(val, &ptr, 0);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if ((v == 0 && val == ptr) || *ptr != '\0') {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' contains extra characters.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (errno == ERANGE) {
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// Coverity; see above. jhrg 5/9/16
|
|
Packit |
a4aae4 |
else if (v > DODS_MAX_ARRAY_INDEX) { // 2^61
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return v;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
double get_float64(const char *val)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "val: " << val << endl);
|
|
Packit |
a4aae4 |
char *ptr;
|
|
Packit |
a4aae4 |
errno = 0; // Clear previous value. 5/21/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
double v = w32strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
double v = strtod(val, &ptr);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (errno == ERANGE || (v == 0.0 && val == ptr) || *ptr != '\0')
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "fabs(" << val << ") = " << fabs(v) << endl);
|
|
Packit |
a4aae4 |
double abs_val = fabs(v);
|
|
Packit |
a4aae4 |
if (abs_val > DODS_DBL_MAX || (abs_val != 0.0 && abs_val < DODS_DBL_MIN))
|
|
Packit |
a4aae4 |
throw Error("The value '" + string(val) + "' is out of range.");;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return v;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
Maybe someday we will really check the Urls to see if they are valid...
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int check_url(const char *)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return TRUE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|