util.cc
// -*- mode: c++; c-basic-offset:4 -*-
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.
// Copyright (c) 2002,2003 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.
// (c) COPYRIGHT URI/MIT 1994-1999
// Please read the full copyright statement in the file COPYRIGHT_URI.
//
// Authors:
// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
// Utility functions used by the api.
//
// jhrg 9/21/94
#include "config.h"
#include <fstream>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
#ifndef TM_IN_SYS_TIME
#include <time.h>
#else
#include <sys/time.h>
#endif
#ifndef WIN32
#include <unistd.h> // for stat
#else
#include <fcntl.h>
#include <io.h>
#include <process.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <algorithm>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include "Array.h"
#include "BaseType.h"
#include "Byte.h"
#include "Float32.h"
#include "Float64.h"
#include "Int16.h"
#include "Int32.h"
#include "Str.h"
#include "UInt16.h"
#include "UInt32.h"
#include "Int64.h"
#include "Int8.h"
#include "UInt64.h"
#include "Error.h"
#include "GNURegex.h"
#include "debug.h"
#include "util.h"
using namespace std;
namespace libdap {
bool is_host_big_endian() {
#ifdef COMPUTE_ENDIAN_AT_RUNTIME
dods_int16 i = 0x0100;
char *c = reinterpret_cast<char *>(&i);
return *c;
#else
#if WORDS_BIGENDIAN
return true;
#else
return false;
#endif
#endif
}
string extract_string_argument(BaseType *arg) {
assert(arg);
if (arg->type() != dods_str_c)
throw Error(malformed_expr, "The function requires a string argument.");
if (!arg->read_p())
throw InternalErr(__FILE__, __LINE__,
"The CE Evaluator built an argument list where some constants held no values.");
return static_cast<Str *>(arg)->value();
}
template <class T> static void set_array_using_double_helper(Array *a, double *src, int src_len) {
assert(a);
assert(src);
assert(src_len > 0);
vector<T> values(src_len);
for (int i = 0; i < src_len; ++i)
values[i] = (T)src[i];
// This copies the values
a->set_value(values, src_len);
}
void set_array_using_double(Array *dest, double *src, int src_len) {
assert(dest);
assert(src);
assert(src_len > 0);
// Simple types are Byte, ..., Float64, String and Url.
if ((dest->type() == dods_array_c && !dest->var()->is_simple_type()) || dest->var()->type() == dods_str_c ||
dest->var()->type() == dods_url_c)
throw InternalErr(__FILE__, __LINE__, "The function requires a numeric-type array argument.");
// Test sizes. Note that Array::length() takes any constraint into account
// when it returns the length. Even if this was removed, the 'helper'
// function this uses calls Vector::val2buf() which uses Vector::width()
// which in turn uses length().
if (dest->length() != src_len)
throw InternalErr(__FILE__, __LINE__,
"The source and destination array sizes don't match (" + long_to_string(src_len) +
" versus " + long_to_string(dest->length()) + ").");
// The types of arguments that the CE Parser will build for numeric
// constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
// Expanded to work for any numeric type so it can be used for more than
// just arguments.
switch (dest->var()->type()) {
case dods_byte_c:
set_array_using_double_helper<dods_byte>(dest, src, src_len);
break;
case dods_uint16_c:
set_array_using_double_helper<dods_uint16>(dest, src, src_len);
break;
case dods_int16_c:
set_array_using_double_helper<dods_int16>(dest, src, src_len);
break;
case dods_uint32_c:
set_array_using_double_helper<dods_uint32>(dest, src, src_len);
break;
case dods_int32_c:
set_array_using_double_helper<dods_int32>(dest, src, src_len);
break;
case dods_float32_c:
set_array_using_double_helper<dods_float32>(dest, src, src_len);
break;
case dods_float64_c:
set_array_using_double_helper<dods_float64>(dest, src, src_len);
break;
// DAP4 support
case dods_uint8_c:
set_array_using_double_helper<dods_byte>(dest, src, src_len);
break;
case dods_int8_c:
set_array_using_double_helper<dods_int8>(dest, src, src_len);
break;
case dods_uint64_c:
set_array_using_double_helper<dods_uint64>(dest, src, src_len);
break;
case dods_int64_c:
set_array_using_double_helper<dods_int64>(dest, src, src_len);
break;
default:
throw InternalErr(__FILE__, __LINE__,
"The argument list built by the CE parser contained an unsupported numeric type.");
}
// Set the read_p property.
dest->set_read_p(true);
}
template <class T> static double *extract_double_array_helper(Array *a) {
assert(a);
int length = a->length();
vector<T> b(length);
a->value(b.data()); // Extract the values of 'a' to 'b'
double *dest = new double[length];
for (int i = 0; i < length; ++i)
dest[i] = (double)b[i];
return dest;
}
double *extract_double_array(Array *a) {
assert(a);
// Simple types are Byte, ..., Float64, String and Url.
if ((a->type() == dods_array_c && !a->var()->is_simple_type()) || a->var()->type() == dods_str_c ||
a->var()->type() == dods_url_c)
throw Error(malformed_expr, "The function requires a DAP numeric-type array argument.");
if (!a->read_p())
throw InternalErr(__FILE__, __LINE__, string("The Array '") + a->name() + "'does not contain values.");
// The types of arguments that the CE Parser will build for numeric
// constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
// Expanded to work for any numeric type so it can be used for more than
// just arguments.
switch (a->var()->type()) {
case dods_byte_c:
return extract_double_array_helper<dods_byte>(a);
case dods_uint16_c:
return extract_double_array_helper<dods_uint16>(a);
case dods_int16_c:
return extract_double_array_helper<dods_int16>(a);
case dods_uint32_c:
return extract_double_array_helper<dods_uint32>(a);
case dods_int32_c:
return extract_double_array_helper<dods_int32>(a);
case dods_float32_c:
return extract_double_array_helper<dods_float32>(a);
case dods_float64_c:
// Should not be copying these values, just read them,
// but older code may depend on the return of this function
// being something that should be deleted, so leave this
// alone. jhrg 2/24/15
return extract_double_array_helper<dods_float64>(a);
// Support for DAP4
case dods_uint8_c:
return extract_double_array_helper<dods_byte>(a);
case dods_int8_c:
return extract_double_array_helper<dods_int8>(a);
case dods_uint64_c:
return extract_double_array_helper<dods_uint64>(a);
case dods_int64_c:
return extract_double_array_helper<dods_int64>(a);
default:
throw InternalErr(__FILE__, __LINE__,
"The argument list built by the CE parser contained an unsupported numeric type.");
}
}
// This helper function assumes 'dest' is the correct size. This should not
// be called when the Array 'a' is a Float64, since the values are already
// in a double array!
template <class T> static void extract_double_array_helper(Array *a, vector<double> &dest) {
assert(a);
assert(dest.size() == (unsigned long)a->length());
int length = a->length();
vector<T> b(length);
a->value(b.data()); // Extract the values of 'a' to 'b'
for (int i = 0; i < length; ++i)
dest[i] = (double)b[i];
}
void extract_double_array(Array *a, vector<double> &dest) {
assert(a);
// Simple types are Byte, ..., Float64, String and Url.
if ((a->type() == dods_array_c && !a->var()->is_simple_type()) || a->var()->type() == dods_str_c ||
a->var()->type() == dods_url_c)
throw Error(malformed_expr, "The function requires a DAP numeric-type array argument.");
if (!a->read_p())
throw InternalErr(__FILE__, __LINE__, string("The Array '") + a->name() + "' does not contain values.");
dest.resize(a->length());
// The types of arguments that the CE Parser will build for numeric
// constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
// Expanded to work for any numeric type so it can be used for more than
// just arguments.
switch (a->var()->type()) {
case dods_byte_c:
return extract_double_array_helper<dods_byte>(a, dest);
case dods_uint16_c:
return extract_double_array_helper<dods_uint16>(a, dest);
case dods_int16_c:
return extract_double_array_helper<dods_int16>(a, dest);
case dods_uint32_c:
return extract_double_array_helper<dods_uint32>(a, dest);
case dods_int32_c:
return extract_double_array_helper<dods_int32>(a, dest);
case dods_float32_c:
return extract_double_array_helper<dods_float32>(a, dest);
case dods_float64_c:
return a->value(dest.data()); // no need to copy the values
// return extract_double_array_helper<dods_float64>(a, dest);
// Support for DAP4
case dods_uint8_c:
return extract_double_array_helper<dods_byte>(a, dest);
case dods_int8_c:
return extract_double_array_helper<dods_int8>(a, dest);
case dods_uint64_c:
return extract_double_array_helper<dods_uint64>(a, dest);
case dods_int64_c:
return extract_double_array_helper<dods_int64>(a, dest);
default:
throw InternalErr(__FILE__, __LINE__,
"The argument list built by the CE parser contained an unsupported numeric type.");
}
}
double extract_double_value(BaseType *arg) {
assert(arg);
// Simple types are Byte, ..., Float64, String and Url.
if (!arg->is_simple_type() || arg->type() == dods_str_c || arg->type() == dods_url_c)
throw Error(malformed_expr, "The function requires a numeric-type argument.");
if (!arg->read_p())
throw InternalErr(__FILE__, __LINE__,
"The Evaluator built an argument list where some constants held no values.");
// The types of arguments that the CE Parser will build for numeric
// constants are limited to Uint32, Int32 and Float64. See ce_expr.y.
// Expanded to work for any numeric type so it can be used for more than
// just arguments.
switch (arg->type()) {
case dods_byte_c:
return (double)(static_cast<Byte *>(arg)->value());
case dods_uint16_c:
return (double)(static_cast<UInt16 *>(arg)->value());
case dods_int16_c:
return (double)(static_cast<Int16 *>(arg)->value());
case dods_uint32_c:
return (double)(static_cast<UInt32 *>(arg)->value());
case dods_int32_c:
return (double)(static_cast<Int32 *>(arg)->value());
case dods_float32_c:
return (double)(static_cast<Float32 *>(arg)->value());
case dods_float64_c:
return static_cast<Float64 *>(arg)->value();
// Support for DAP4 types.
case dods_uint8_c:
return (double)(static_cast<Byte *>(arg)->value());
case dods_int8_c:
return (double)(static_cast<Int8 *>(arg)->value());
case dods_uint64_c:
return (double)(static_cast<UInt64 *>(arg)->value());
case dods_int64_c:
return (double)(static_cast<Int64 *>(arg)->value());
default:
throw InternalErr(__FILE__, __LINE__,
"The argument list built by the parser contained an unsupported numeric type.");
}
}
// Remove spaces from the start of a URL and from the start of any constraint
// expression it contains. 4/7/98 jhrg
string prune_spaces(const string &name) {
// If the URL does not even have white space return.
if (name.find_first_of(' ') == name.npos)
return name;
else {
// Strip leading spaces from http://...
unsigned int i = name.find_first_not_of(' ');
string tmp_name = name.substr(i);
// Strip leading spaces from constraint part (following `?').
unsigned int j = tmp_name.find('?') + 1;
i = tmp_name.find_first_not_of(' ', j);
tmp_name.erase(j, i - j);
return tmp_name;
}
}
// Compare elements in a list of (BaseType *)s and return true if there are
// no duplicate elements, otherwise return false.
bool unique_names(vector<BaseType *> l, const string &var_name, const string &type_name, string &msg) {
// copy the identifier names to a vector
vector<string> names(l.size());
int nelem = 0;
typedef std::vector<BaseType *>::const_iterator citer;
for (citer i = l.begin(); i != l.end(); i++) {
assert(*i);
names[nelem++] = (*i)->name();
DBG(cerr << "NAMES[" << nelem - 1 << "]=" << names[nelem - 1] << endl);
}
// sort the array of names
sort(names.begin(), names.end());
// sort the array of names
sort(names.begin(), names.end());
// look for any instance of consecutive names that are ==
for (int j = 1; j < nelem; ++j) {
if (names[j - 1] == names[j]) {
ostringstream oss;
oss << "The variable `" << names[j] << "' is used more than once in " << type_name << " `" << var_name
<< "'";
msg = oss.str();
return false;
}
}
return true;
}
const char *libdap_root() { return LIBDAP_ROOT; }
extern "C" const char *libdap_version() {
// return PACKAGE_VERSION;
// Switched to CVER which is <version>-<build_number>
return CVER;
}
extern "C" const char *libdap_name() { return PACKAGE_NAME; }
string systime() {
time_t TimBin;
if (time(&TimBin) == (time_t)-1)
return {"time() error"};
else {
char ctime_value[32];
const char *ret = ctime_r(&TimBin, ctime_value);
if (ret) {
string TimStr = ctime_value;
return TimStr.substr(0, TimStr.size() - 2); // remove the \n
} else
return {"Unknown"};
}
}
void downcase(string &s) {
for (unsigned int i = 0; i < s.length(); i++)
s[i] = tolower(s[i]);
}
bool is_quoted(const string &s) { return (!s.empty() && s[0] == '\"' && s[s.length() - 1] == '\"'); }
string remove_quotes(const string &s) {
if (is_quoted(s))
return s.substr(1, s.length() - 2);
else
return s;
}
Type get_type(const char *name) {
if (strcmp(name, "Byte") == 0)
return dods_byte_c;
if (strcmp(name, "Char") == 0)
return dods_char_c;
if (strcmp(name, "Int8") == 0)
return dods_int8_c;
if (strcmp(name, "UInt8") == 0)
return dods_uint8_c;
if (strcmp(name, "Int16") == 0)
return dods_int16_c;
if (strcmp(name, "UInt16") == 0)
return dods_uint16_c;
if (strcmp(name, "Int32") == 0)
return dods_int32_c;
if (strcmp(name, "UInt32") == 0)
return dods_uint32_c;
if (strcmp(name, "Int64") == 0)
return dods_int64_c;
if (strcmp(name, "UInt64") == 0)
return dods_uint64_c;
if (strcmp(name, "Float32") == 0)
return dods_float32_c;
if (strcmp(name, "Float64") == 0)
return dods_float64_c;
if (strcmp(name, "String") == 0)
return dods_str_c;
// accept both spellings; this might be confusing since URL
// could be filtered through code and come out Url. Don't know...
// jhrg 8/15/13
if (strcmp(name, "Url") == 0 || strcmp(name, "URL") == 0)
return dods_url_c;
if (strcmp(name, "Enum") == 0)
return dods_enum_c;
if (strcmp(name, "Opaque") == 0)
return dods_opaque_c;
if (strcmp(name, "Array") == 0)
return dods_array_c;
if (strcmp(name, "Structure") == 0)
return dods_structure_c;
if (strcmp(name, "Sequence") == 0)
return dods_sequence_c;
if (strcmp(name, "Grid") == 0)
return dods_grid_c;
return dods_null_c;
}
string D2type_name(Type t) {
switch (t) {
case dods_null_c:
return string("Null");
case dods_byte_c:
return string("Byte");
case dods_int16_c:
return string("Int16");
case dods_uint16_c:
return string("UInt16");
case dods_int32_c:
return string("Int32");
case dods_uint32_c:
return string("UInt32");
case dods_float32_c:
return string("Float32");
case dods_float64_c:
return string("Float64");
case dods_str_c:
return string("String");
case dods_url_c:
return string("Url");
case dods_array_c:
return string("Array");
case dods_structure_c:
return string("Structure");
case dods_sequence_c:
return string("Sequence");
case dods_grid_c:
return string("Grid");
default:
throw InternalErr(__FILE__, __LINE__, "Unknown type.");
}
}
string D4type_name(Type t) {
switch (t) {
case dods_null_c:
return string("Null");
case dods_byte_c:
return string("Byte");
case dods_char_c:
return string("Char");
case dods_int8_c:
return string("Int8");
case dods_uint8_c:
return string("UInt8");
case dods_int16_c:
return string("Int16");
case dods_uint16_c:
return string("UInt16");
case dods_int32_c:
return string("Int32");
case dods_uint32_c:
return string("UInt32");
case dods_int64_c:
return string("Int64");
case dods_uint64_c:
return string("UInt64");
case dods_enum_c:
return string("Enum");
case dods_float32_c:
return string("Float32");
case dods_float64_c:
return string("Float64");
case dods_str_c:
return string("String");
case dods_url_c:
return string("URL");
case dods_opaque_c:
return string("Opaque");
case dods_array_c:
return string("Array");
case dods_structure_c:
return string("Structure");
case dods_sequence_c:
return string("Sequence");
case dods_group_c:
return string("Group");
default:
throw InternalErr(__FILE__, __LINE__, "Unknown type.");
}
}
string type_name(Type t) {
try {
return D4type_name(t);
} catch (...) {
return D2type_name(t);
}
}
bool is_simple_type(Type t) {
switch (t) {
case dods_byte_c:
case dods_char_c:
case dods_int8_c:
case dods_uint8_c:
case dods_int16_c:
case dods_uint16_c:
case dods_int32_c:
case dods_uint32_c:
case dods_int64_c:
case dods_uint64_c:
case dods_float32_c:
case dods_float64_c:
case dods_str_c:
case dods_url_c:
case dods_enum_c:
case dods_opaque_c:
return true;
case dods_null_c:
case dods_array_c:
case dods_structure_c:
case dods_sequence_c:
case dods_grid_c:
case dods_group_c:
default:
return false;
}
}
bool is_vector_type(Type t) {
switch (t) {
case dods_null_c:
case dods_byte_c:
case dods_char_c:
case dods_int8_c:
case dods_uint8_c:
case dods_int16_c:
case dods_uint16_c:
case dods_int32_c:
case dods_uint32_c:
case dods_int64_c:
case dods_uint64_c:
case dods_float32_c:
case dods_float64_c:
case dods_str_c:
case dods_url_c:
case dods_enum_c:
case dods_opaque_c:
return false;
case dods_array_c:
return true;
case dods_structure_c:
case dods_sequence_c:
case dods_grid_c:
case dods_group_c:
default:
return false;
}
}
bool is_constructor_type(Type t) {
switch (t) {
case dods_null_c:
case dods_byte_c:
case dods_char_c:
case dods_int8_c:
case dods_uint8_c:
case dods_int16_c:
case dods_uint16_c:
case dods_int32_c:
case dods_uint32_c:
case dods_int64_c:
case dods_uint64_c:
case dods_float32_c:
case dods_float64_c:
case dods_str_c:
case dods_url_c:
case dods_enum_c:
case dods_opaque_c:
case dods_array_c:
return false;
case dods_structure_c:
case dods_sequence_c:
case dods_grid_c:
case dods_group_c:
default:
return true;
}
}
bool is_integer_type(Type t) {
switch (t) {
case dods_byte_c:
case dods_char_c:
case dods_int8_c:
case dods_uint8_c:
case dods_int16_c:
case dods_uint16_c:
case dods_int32_c:
case dods_uint32_c:
case dods_int64_c:
case dods_uint64_c:
return true;
default:
return false;
}
}
bool dir_exists(const string &dir) {
struct stat buf;
return (stat(dir.c_str(), &buf) == 0) && (buf.st_mode & S_IFDIR);
}
// Jose Garcia
void append_long_to_string(long val, int base, string &str_val) {
// The array digits contains 36 elements which are the
// posible valid digits for out bases in the range
// [2,36]
char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// result of val / base
ldiv_t r;
if (base > 36 || base < 2) {
// no conversion if wrong base
std::invalid_argument ex("The parameter base has an invalid value.");
throw ex;
}
if (val < 0)
str_val += '-';
r = ldiv(labs(val), base);
// output digits of val/base first
if (r.quot > 0)
append_long_to_string(r.quot, base, str_val);
// output last digit
str_val += digits[(int)r.rem];
}
// base defaults to 10
string long_to_string(long val, int base) {
string s;
append_long_to_string(val, base, s);
return s;
}
// Jose Garcia
void append_double_to_string(const double &num, string &str) {
// s having 100 characters should be enough for sprintf to do its job.
// I want to banish all instances of sprintf. 10/5/2001 jhrg
ostringstream oss;
oss.precision(9);
oss << num;
str += oss.str();
}
string double_to_string(const double &num) {
string s;
append_double_to_string(num, s);
return s;
}
// Given a pathname, return the file at the end of the path. This is used
// when reporting errors (maybe other times, too) to keep the server from
// revealing too much about its organization when sending error responses
// back to clients. 10/11/2000 jhrg
// MT-safe. 08/05/02 jhrg
#ifdef WIN32
static const char path_sep[] = {"\\"};
#else
static const char path_sep[] = {"/"};
#endif
string path_to_filename(string path) {
string::size_type pos = path.rfind(path_sep);
return (pos == string::npos) ? path : path.substr(++pos);
}
#define CHECK_BIT(tab, bit) (tab[(bit) / 8] & (1 << ((bit) % 8)))
#define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
/*
* globchars() - build a bitlist to check for character group match
*/
static void globchars(const char *s, const char *e, char *b) {
int neg = 0;
memset(b, '\0', BITLISTSIZE);
if (*s == '^')
neg++, s++;
while (s < e) {
int c;
if (s + 2 < e && s[1] == '-') {
for (c = s[0]; c <= s[2]; c++)
b[c / 8] |= (1 << (c % 8));
s += 3;
} else {
c = *s++;
b[c / 8] |= (1 << (c % 8));
}
}
if (neg) {
int i;
for (i = 0; i < BITLISTSIZE; i++)
b[i] ^= 0377;
}
/* Don't include \0 in either $[chars] or $[^chars] */
b[0] &= 0376;
}
int glob(const char *c, const char *s) {
if (!c || !s)
return 1;
char bitlist[BITLISTSIZE];
int i = 0;
for (;;) {
++i;
switch (*c++) {
case '\0':
return *s ? -1 : 0;
case '?':
if (!*s++)
return i /*1*/;
break;
case '[': {
/* scan for matching ] */
const char *here = c;
do {
if (!*c++)
return i /*1*/;
} while (here == c || *c != ']');
c++;
/* build character class bitlist */
globchars(here, c, bitlist);
if (!CHECK_BIT(bitlist, *(unsigned char *)s))
return i /*1*/;
s++;
break;
}
case '*': {
const char *here = s;
while (*s)
s++;
/* Try to match the rest of the pattern in a recursive */
/* call. If the match fails we'll back up chars, retrying. */
while (s != here) {
int r;
/* A fast path for the last token in a pattern */
r = *c ? glob(c, s) : *s ? -1 : 0;
if (!r)
return 0;
else if (r < 0)
return i /*1*/;
--s;
}
break;
}
case '\\':
/* Force literal match of next char. */
if (!*c || *s != *c) {
return i /*1*/;
} else {
s++;
c++;
}
break;
default:
if (*s++ != c[-1])
return i /*1*/;
break;
}
}
}
bool size_ok(unsigned int sz, unsigned int nelem) { return (sz > 0 && nelem < UINT_MAX / sz); }
bool pathname_ok(const string &path, bool strict) {
if (path.length() > 255)
return false;
#if 0
// Make this use a const regex 12/1/21
Regex name("[-0-9A-z_./]+");
if (!strict) name = "[:print:]+";
#endif
const Regex strict_name("[-0-9A-z_./]+");
const Regex relaxed_name("[:print:]+");
#if 0
string::size_type len = path.length();
#endif
unsigned long result;
if (strict)
result = strict_name.match(path);
else
result = relaxed_name.match(path);
return (result == path.length());
#if 0
// Protect against casting too big an uint to int
// if LEN is bigger than the max int32, the second test can't work
// This makes no sense - len can never be > 255 given the test at the
// start of this function. jhrg 12/1/21
if (len > INT_MAX || result != static_cast<int>(len)) return false;
return true;
#endif
}
string dap_version() {
return (string) "OPeNDAP DAP/" + libdap_version() + ": compiled on " + __DATE__ + ":" + __TIME__;
}
string open_temp_fstream(ofstream &f, const string &name_template, const string &suffix /* = "" */) {
vector<char> name;
copy(name_template.begin(), name_template.end(), back_inserter(name));
if (!suffix.empty())
copy(suffix.begin(), suffix.end(), back_inserter(name));
name.push_back('\0');
// Use mkstemp to make and open the temp file atomically
int tmpfile = mkstemps(name.data(), suffix.length());
if (tmpfile == -1)
throw Error(internal_error, "Could not make a temporary file.");
// Open the file using C++ ofstream; get a C++ fstream object
f.open(name.data());
// Close the file descriptor; the file stays open because of the fstream object
close(tmpfile);
// Now test that the fstream object is valid
if (f.fail())
throw Error(internal_error, "Could not make a temporary file.");
return string(name.data());
}
} // namespace libdap
libdap::Array
A multidimensional array of identical data types.
Definition Array.h:121
libdap::BaseType
The basic data type for the DODS DAP types.
Definition BaseType.h:118
libdap::BaseType::name
virtual string name() const
Returns the name of the class instance.
Definition BaseType.cc:296
libdap::BaseType::read_p
virtual bool read_p()
Has this variable been read?
Definition BaseType.cc:410
libdap::BaseType::is_simple_type
virtual bool is_simple_type() const
Returns true if the instance is a numeric, string or URL type variable.
Definition BaseType.cc:347
libdap::BaseType::type
virtual Type type() const
Returns the type of the class instance.
Definition BaseType.cc:329
libdap::Byte
Holds a single byte.
Definition Byte.h:59
libdap::Error
A class for error processing.
Definition Error.h:92
libdap::Float32
Holds a 32-bit floating point value.
Definition Float32.h:59
libdap::Float64
Holds a 64-bit (double precision) floating point value.
Definition Float64.h:58
libdap::Int16
Holds a 16-bit signed integer value.
Definition Int16.h:57
libdap::Int32
Holds a 32-bit signed integer.
Definition Int32.h:63
libdap::Int64
Holds a64-bit signed integer.
Definition Int64.h:48
libdap::Int8
Holds an 8-bit signed integer value.
Definition Int8.h:41
libdap::InternalErr
A class for software fault reporting.
Definition InternalErr.h:61
libdap::Regex
Regular expression matching.
Definition GNURegex.h:54
libdap::Regex::match
int match(const char *s, int len, int pos=0) const
Does the pattern match.
Definition GNURegex.cc:136
libdap::Str
Holds character string data.
Definition Str.h:61
libdap::UInt16
Holds an unsigned 16-bit integer.
Definition UInt16.h:55
libdap::UInt32
Holds a 32-bit unsigned integer.
Definition UInt32.h:57
libdap::UInt64
Holds a 64-bit unsigned integer.
Definition UInt64.h:47
libdap::Vector::length
int length() const override
Returns the number of elements in the vector. Note that some child classes of Vector use the length o...
Definition Vector.h:210
libdap::Vector::set_read_p
void set_read_p(bool state) override
Indicates that the data is ready to send.
Definition Vector.cc:389
libdap::Vector::var
BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr) override
Definition Vector.cc:469
libdap
top level DAP object to house generic methods
Definition AlarmHandler.h:35
libdap::Type
Type
Identifies the data type.
Definition Type.h:94
libdap::open_temp_fstream
string open_temp_fstream(ofstream &f, const string &name_template, const string &suffix)
Definition util.cc:1214
libdap::size_ok
bool size_ok(unsigned int sz, unsigned int nelem)
sanitize the size of an array. Test for integer overflow when dynamically allocating an array.
Definition util.cc:1138
libdap::remove_quotes
string remove_quotes(const string &s)
Definition util.cc:562
libdap::path_to_filename
string path_to_filename(string path)
Definition util.cc:988
libdap::is_host_big_endian
bool is_host_big_endian()
Does this host use big-endian byte order?
Definition util.cc:94
libdap::libdap_version
const char * libdap_version()
Definition util.cc:511
libdap::extract_double_value
double extract_double_value(BaseType *arg)
Definition util.cc:395
libdap::prune_spaces
string prune_spaces(const string &name)
Definition util.cc:451
libdap::type_name
string type_name(Type t)
Definition util.cc:753
libdap::set_array_using_double
void set_array_using_double(Array *dest, double *src, int src_len)
Definition util.cc:164
libdap::is_simple_type
bool is_simple_type(Type t)
Returns true if the instance is a numeric, string or URL type variable.
Definition util.cc:766
libdap::dir_exists
bool dir_exists(const string &dir)
Definition util.cc:912
libdap::pathname_ok
bool pathname_ok(const string &path, bool strict)
Does the string name a potentially valid pathname? Test the given pathname to verify that it is a val...
Definition util.cc:1156
libdap::downcase
void downcase(string &s)
Definition util.cc:544
libdap::D2type_name
string D2type_name(Type t)
Returns the type of the class instance as a string. Supports all DAP2 types and not the DAP4-only typ...
Definition util.cc:644
libdap::D4type_name
string D4type_name(Type t)
Returns the type of the class instance as a string. Supports all DAP4 types and not the DAP2-only typ...
Definition util.cc:688
libdap::systime
string systime()
Definition util.cc:524
libdap::is_constructor_type
bool is_constructor_type(Type t)
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable.
Definition util.cc:848
libdap::is_vector_type
bool is_vector_type(Type t)
Returns true if the instance is a vector (i.e., array) type variable.
Definition util.cc:805
libdap::is_integer_type
bool is_integer_type(Type t)
Definition util.cc:888
libdap::glob
int glob(const char *c, const char *s)
Definition util.cc:1049
libdap::extract_string_argument
string extract_string_argument(BaseType *arg)
Definition util.cc:118
libdap::get_type
ObjectType get_type(const string &value)
Definition mime_util.cc:300
libdap::extract_double_array
double * extract_double_array(Array *a)
Definition util.cc:257
libdap::is_quoted
bool is_quoted(const string &s)
Definition util.cc:554
libdap::dap_version
string dap_version()
Definition util.cc:1198