|
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 1994-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 |
// Methods for the class DAS - a class used to parse the dataset attribute
|
|
Packit |
a4aae4 |
// structure.
|
|
Packit |
a4aae4 |
//
|
|
Packit |
a4aae4 |
// jhrg 7/25/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cstdio>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
a4aae4 |
#include <unistd.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
#include <io.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <iostream>
|
|
Packit |
a4aae4 |
#include <string>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "DAS.h"
|
|
Packit |
a4aae4 |
#include "AttrTable.h"
|
|
Packit |
a4aae4 |
#include "Error.h"
|
|
Packit |
a4aae4 |
#include "InternalErr.h"
|
|
Packit |
a4aae4 |
#include "parser.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Glue routines declared in das.lex
|
|
Packit |
a4aae4 |
extern void das_switch_to_buffer(void *new_buffer);
|
|
Packit |
a4aae4 |
extern void das_delete_buffer(void * buffer);
|
|
Packit |
a4aae4 |
extern void *das_buffer(FILE *fp);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//extern void dasrestart(FILE *yyin);
|
|
Packit |
a4aae4 |
//extern int dasparse(void *arg); // defined in das.tab.c
|
|
Packit |
a4aae4 |
extern int dasparse(libdap::parser_arg *arg); // defined in das.tab.c
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void DAS::duplicate(const DAS &src)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// If the container field is set, perform a deep copy
|
|
Packit |
a4aae4 |
if (src.d_container)
|
|
Packit |
a4aae4 |
d_container = new AttrTable(*src.d_container);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
d_container = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_container_name = src.d_container_name;
|
|
Packit |
a4aae4 |
d_attrs = src.d_attrs;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DAS &DAS::operator=(const DAS &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (this == &rhs)
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
duplicate(rhs);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Sets the name of the current attribute container when multiple
|
|
Packit |
a4aae4 |
* files used to build this DAS.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param cn container name
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void DAS::container_name(const string &cn)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
// We want to find a top level attribute table with the given name. So
|
|
Packit |
a4aae4 |
// set d_container to null first so that we aren't searching some
|
|
Packit |
a4aae4 |
// previous container
|
|
Packit |
a4aae4 |
if (cn != d_container_name) {
|
|
Packit |
a4aae4 |
d_container = 0;
|
|
Packit |
a4aae4 |
if (!cn.empty()) {
|
|
Packit |
a4aae4 |
d_container = get_table(cn);
|
|
Packit |
a4aae4 |
if (!d_container) {
|
|
Packit |
a4aae4 |
d_container = add_table(cn, new AttrTable);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
d_container_name = cn;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the number of attributes in the current attribute table
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* If the there is a container set, then return the number of variable
|
|
Packit |
a4aae4 |
* attribute tables for the current container. If not set then return the
|
|
Packit |
a4aae4 |
* number of current attribute tables in the outermost attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
unsigned int DAS::get_size() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->get_size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.get_size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief erase all attributes in this DAS
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void DAS::erase()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
d_container->erase();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
d_attrs.erase();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns a reference to the attribute table for the first variable.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter DAS::var_begin()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->attr_begin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.attr_begin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns a reference to the end of the attribute table. Does not
|
|
Packit |
a4aae4 |
* point to an attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter DAS::var_end()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->attr_end();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.attr_end();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the name of the referenced variable attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
string DAS::get_name(AttrTable::Attr_iter &i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->get_name(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.get_name(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the referenced variable attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
DAS::get_table(AttrTable::Attr_iter &i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->get_attr_table(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.get_attr_table(i);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Returns the variable attribute table with the given name.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
DAS::get_table(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
return d_container->get_attr_table(name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.get_attr_table(name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Adds an attribute table to the DAS.
|
|
Packit |
a4aae4 |
@name add_table()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Adds a variable attribute table to the DAS or the current
|
|
Packit |
a4aae4 |
* dataset container attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
DAS::add_table( const string &name, AttrTable *at )
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
at->set_is_global_attribute(false);
|
|
Packit |
a4aae4 |
return d_container->append_container(at, name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return d_attrs.append_container( at, name ) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Reads a DAS in from an external source.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@name parse()
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Reads a DAS from the named file.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Read attributes from a file. Returns false if unable to open
|
|
Packit |
a4aae4 |
the file, otherwise returns the result of the mfunc parse. */
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DAS::parse(string fname)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
FILE *in = fopen(fname.c_str(), "r");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw Error(cannot_read_file, "Could not open: " + fname);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
parse(in);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int res = fclose(in);
|
|
Packit |
a4aae4 |
if (res) {
|
|
Packit |
a4aae4 |
DBG(cerr << "DAS::parse - Failed to close file " << (void *)in << endl ;) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Read attributes from a file descriptor.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If the file descriptor cannot be fdopen'd, return false, otherwise
|
|
Packit |
a4aae4 |
return the status of the mfunc parse.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
\note Added call to dup() within fdopen so that once the FILE * is
|
|
Packit |
a4aae4 |
closed the decriptor fd will not also be closed (instead the
|
|
Packit |
a4aae4 |
duplicate descriptor will be closed). Thus further information can
|
|
Packit |
a4aae4 |
be read from the descriptor fd.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DAS::parse(int fd)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#ifdef WIN32
|
|
Packit |
a4aae4 |
int new_fd = _dup(fd);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
int new_fd = dup(fd);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (new_fd < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not access file.");
|
|
Packit |
a4aae4 |
FILE *in = fdopen(new_fd, "r");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not access file.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
parse(in);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int res = fclose(in);
|
|
Packit |
a4aae4 |
if (res) {
|
|
Packit |
a4aae4 |
DBG(cerr << "DAS::parse(fd) - Failed to close " << (void *)in << endl ;) ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Reads a DAS from an open file descriptor.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Read attributes from in (which defaults to stdin). If
|
|
Packit |
a4aae4 |
dasrestart() fails, return false, otherwise return the status
|
|
Packit |
a4aae4 |
of dasparse().
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DAS::parse(FILE *in)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (!in) {
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Null input stream.");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void *buffer = das_buffer(in);
|
|
Packit |
a4aae4 |
das_switch_to_buffer(buffer);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
parser_arg arg(this);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//bool status = dasparse((void *) & arg) == 0;
|
|
Packit |
a4aae4 |
bool status = dasparse(&arg) == 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
das_delete_buffer(buffer);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// STATUS is the result of the parser function; if a recoverable error
|
|
Packit |
a4aae4 |
// was found it will be true but arg.status() will be false.
|
|
Packit |
a4aae4 |
if (!status || !arg.status()) {// Check parse result
|
|
Packit |
a4aae4 |
if (arg.error())
|
|
Packit |
a4aae4 |
throw *arg.error();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Creates an ASCII representation of a DAS on the given output
|
|
Packit |
a4aae4 |
stream.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
When an identifier contains a character that contains
|
|
Packit |
a4aae4 |
characters that cannot be present in a URL (e.g., a space)
|
|
Packit |
a4aae4 |
AttrTable::print replaces those characters with WWW
|
|
Packit |
a4aae4 |
escape codes. 7/13/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param out output FILE on which to print the DAS
|
|
Packit |
a4aae4 |
@param dereference If true, follow aliases. Default is false.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DAS::print(FILE *out, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
fprintf(out, "Attributes {\n") ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_attrs.print(out, " ", dereference);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
fprintf(out, "}\n") ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Creates an ASCII representation of a DAS on the given output
|
|
Packit |
a4aae4 |
stream.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
When an identifier contains a character that contains
|
|
Packit |
a4aae4 |
characters that cannot be present in a URL (e.g., a space)
|
|
Packit |
a4aae4 |
AttrTable::print replaces those characters with WWW
|
|
Packit |
a4aae4 |
escape codes. 7/13/2001 jhrg
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param out output ostream on which to print the DAS
|
|
Packit |
a4aae4 |
@param dereference If true, follow aliases. Default is false.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
DAS::print(ostream &out, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
out << "Attributes {\n" ;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_attrs.print(out, " ", dereference);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << "}\n" ;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief dumps information about this object
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Displays the pointer value of this instance and then calls parent dump
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param strm C++ i/o stream to dump the information to
|
|
Packit |
a4aae4 |
* @return void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void DAS::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "DAS::dump - (" << (void *) this << ")" << endl;
|
|
Packit |
a4aae4 |
DapIndent::Indent();
|
|
Packit |
a4aae4 |
if (d_container) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "current container: " << d_container_name << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "current container: NONE" << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
d_attrs.dump(strm);
|
|
Packit |
a4aae4 |
DapIndent::UnIndent();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|