Blame AttrTable.h

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
// An AttrTable is a table of attributes (type-name-value tuples).
Packit a4aae4
Packit a4aae4
#ifndef _attrtable_h
Packit a4aae4
#define _attrtable_h 1
Packit a4aae4
Packit a4aae4
Packit a4aae4
#include <string>
Packit a4aae4
#include <vector>
Packit a4aae4
Packit a4aae4
#ifndef _error_h
Packit a4aae4
#include "Error.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
using std::vector;
Packit a4aae4
using std::string;
Packit a4aae4
using std::vector;
Packit a4aae4
Packit a4aae4
#ifndef A_DapObj_h
Packit a4aae4
#include "DapObj.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
#ifndef XMLWRITER_H_
Packit a4aae4
#include "XMLWriter.h"
Packit a4aae4
#endif
Packit a4aae4
Packit a4aae4
namespace libdap
Packit a4aae4
{
Packit a4aae4
Packit a4aae4
/** AttrType identifies the data types which may appear in an
Packit a4aae4
    attribute table object.
Packit a4aae4
Packit a4aae4
    \code
Packit a4aae4
    enum AttrType {
Packit a4aae4
 Attr_unknown,
Packit a4aae4
 Attr_container,
Packit a4aae4
 Attr_byte,
Packit a4aae4
 Attr_int16,
Packit a4aae4
 Attr_uint16,
Packit a4aae4
 Attr_int32,
Packit a4aae4
 Attr_uint32,
Packit a4aae4
 Attr_float32,
Packit a4aae4
 Attr_float64,
Packit a4aae4
 Attr_string,
Packit a4aae4
 Attr_url,
Packit a4aae4
 Attr_other_xml
Packit a4aae4
    };
Packit a4aae4
    \endcode
Packit a4aae4
Packit a4aae4
    @see AttrTable */
Packit a4aae4
enum AttrType {
Packit a4aae4
    Attr_unknown,
Packit a4aae4
    Attr_container,
Packit a4aae4
    Attr_byte,
Packit a4aae4
    Attr_int16,
Packit a4aae4
    Attr_uint16,
Packit a4aae4
    Attr_int32,
Packit a4aae4
    Attr_uint32,
Packit a4aae4
    Attr_float32,
Packit a4aae4
    Attr_float64,
Packit a4aae4
    Attr_string,
Packit a4aae4
    Attr_url,
Packit a4aae4
    Attr_other_xml
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
string AttrType_to_String(const AttrType at);
Packit a4aae4
AttrType String_to_AttrType(const string &s);
Packit a4aae4
Packit a4aae4
/** An AttrTable (``Attribute Table'') stores a set of names and, for
Packit a4aae4
    each name, either a type and a value, or another attribute table.
Packit a4aae4
    The attribute value can be a vector containing many values of the
Packit a4aae4
    same type.  The attributes can have any of the types listed in the
Packit a4aae4
    <tt>AttrType</tt> list.  However, all attribute types are stored as
Packit a4aae4
    string data, except for the container type, which is stored as a
Packit a4aae4
    pointer to another attribute table.
Packit a4aae4
Packit a4aae4
    Each element in the attribute table can itself be an attribute
Packit a4aae4
    table.  The table can also contain ``alias'' attributes whose
Packit a4aae4
    value is given by the value of another attribute to which it is
Packit a4aae4
    linked.
Packit a4aae4
Packit a4aae4
    The attribute tables have a standard printed representation.
Packit a4aae4
    There is a member function <tt>print()</tt> for writing this form.  Use
Packit a4aae4
    the <tt>DAS::parse()</tt> function to read the printed form.
Packit a4aae4
Packit a4aae4
    An attribute table might look something like this:
Packit a4aae4
Packit a4aae4
    \verbatim
Packit a4aae4
    string long_name "Weekly Means of Sea Surface Temperature";
Packit a4aae4
    actual_range {
Packit a4aae4
        Float64 min -1.8;
Packit a4aae4
        Float64 max 35.09;
Packit a4aae4
    }
Packit a4aae4
    string units "degC";
Packit a4aae4
    conversion_data {
Packit a4aae4
        Float64 add_offset 0.;
Packit a4aae4
        Float64 scale_factor 0.0099999998;
Packit a4aae4
    }
Packit a4aae4
    Int32 missing_value 32767;
Packit a4aae4
    \endverbatim
Packit a4aae4
Packit a4aae4
    Here, <tt>long_name</tt>, <tt>units</tt>, and
Packit a4aae4
    <tt>missing_value</tt> are simple
Packit a4aae4
    attributes, and <tt>actual_range</tt> and <tt>conversion_data</tt>
Packit a4aae4
    are container attributes containing other attribute tables.
Packit a4aae4
Packit a4aae4
	@note This class is used only for DAP2.
Packit a4aae4
Packit a4aae4
    @brief Contains the attributes for a dataset.
Packit a4aae4
    @see DAS
Packit a4aae4
    @see AttrType */
Packit a4aae4
class AttrTable : public DapObj
Packit a4aae4
{
Packit a4aae4
    // entry needs to be made public to make up for issues with this class'
Packit a4aae4
    // design. It should probably be moved to it's own class. 05/22/03 jhrg
Packit a4aae4
public:
Packit a4aae4
    /** Each AttrTable has zero or more entries. Instead of accessing this
Packit a4aae4
    struct's members directly, use AttrTable methods.
Packit a4aae4
Packit a4aae4
    This struct is public because its type is used in public typedefs. */
Packit a4aae4
    struct entry
Packit a4aae4
    {
Packit a4aae4
        string name;
Packit a4aae4
        AttrType type;
Packit a4aae4
Packit a4aae4
        bool is_alias;
Packit a4aae4
        string aliased_to;
Packit a4aae4
Packit a4aae4
        bool is_global; // use this to mark non-container attributes. see below.
Packit a4aae4
Packit a4aae4
        // If type == Attr_container, use attributes to read the contained
Packit a4aae4
        // table, otherwise use attr to read the vector of values.
Packit a4aae4
        AttrTable *attributes;
Packit a4aae4
        std::vector<string> *attr; // a vector of values. jhrg 12/5/94
Packit a4aae4
Packit a4aae4
        entry(): name(""), type(Attr_unknown), is_alias(false),
Packit a4aae4
                aliased_to(""), is_global(true), attributes(0), attr(0) {}
Packit a4aae4
Packit a4aae4
        entry(const entry &rhs): name(rhs.name), type(rhs.type), is_alias(rhs.is_alias),
Packit a4aae4
                aliased_to(rhs.aliased_to), is_global(rhs.is_global),attributes(0), attr(0)
Packit a4aae4
        {
Packit a4aae4
            clone(rhs);
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        void delete_entry()
Packit a4aae4
        {
Packit a4aae4
            if (is_alias) // alias copies the pointers.
Packit a4aae4
                return;
Packit a4aae4
            if (type == Attr_container) {
Packit a4aae4
                delete attributes; attributes = 0;
Packit a4aae4
            }
Packit a4aae4
            else {
Packit a4aae4
                delete attr; attr = 0;
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        virtual ~entry()
Packit a4aae4
        {
Packit a4aae4
            delete_entry();
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        void clone(const entry &rhs)
Packit a4aae4
        {
Packit a4aae4
#if 0
Packit a4aae4
            name = rhs.name;
Packit a4aae4
            type = rhs.type;
Packit a4aae4
            is_alias = rhs.is_alias;
Packit a4aae4
            aliased_to = rhs.aliased_to;
Packit a4aae4
            is_global = rhs.is_global;
Packit a4aae4
#endif
Packit a4aae4
            switch (rhs.type) {
Packit a4aae4
            case Attr_unknown:
Packit a4aae4
                break;
Packit a4aae4
            case Attr_container: {
Packit a4aae4
                if (rhs.is_alias)
Packit a4aae4
                    attributes = rhs.attributes;
Packit a4aae4
                else
Packit a4aae4
                    attributes = new AttrTable(*rhs.attributes);
Packit a4aae4
                break;
Packit a4aae4
            }
Packit a4aae4
            default: {
Packit a4aae4
                if (rhs.is_alias)
Packit a4aae4
                    attr = rhs.attr;
Packit a4aae4
                else
Packit a4aae4
                    attr = new std::vector<string>(*rhs.attr);
Packit a4aae4
                break;
Packit a4aae4
            }
Packit a4aae4
            }
Packit a4aae4
        }
Packit a4aae4
Packit a4aae4
        entry &operator=(const entry &rhs)
Packit a4aae4
        {
Packit a4aae4
            if (this != &rhs) {
Packit a4aae4
                delete_entry();
Packit a4aae4
                clone(rhs);
Packit a4aae4
            }
Packit a4aae4
            return *this;
Packit a4aae4
        }
Packit a4aae4
    };
Packit a4aae4
Packit a4aae4
    typedef std::vector<entry *>::const_iterator Attr_citer ;
Packit a4aae4
    typedef std::vector<entry *>::iterator Attr_iter ;
Packit a4aae4
Packit a4aae4
private:
Packit a4aae4
    string d_name;
Packit a4aae4
    AttrTable *d_parent;
Packit a4aae4
    std::vector<entry *> attr_map;
Packit a4aae4
Packit a4aae4
    // Use this to mark container attributes. Look at the methods
Packit a4aae4
    // is_global_attribute() and set_is_...., esp. at the versions that take
Packit a4aae4
    // an iterator. This code is tricky because it has to track both whole
Packit a4aae4
    // containers that are global and individual attributes that are 'global'
Packit a4aae4
    // relative to a constructor. That is, there are some attributes that are
Packit a4aae4
    // bound to a container and not any of the container's children.
Packit a4aae4
    bool d_is_global_attribute;
Packit a4aae4
Packit a4aae4
    void delete_attr_table();
Packit a4aae4
Packit a4aae4
    friend class AttrTableTest;
Packit a4aae4
Packit a4aae4
protected:
Packit a4aae4
    void clone(const AttrTable &at);
Packit a4aae4
Packit a4aae4
    void simple_print(FILE *out, string pad, Attr_iter i,
Packit a4aae4
                      bool dereference);
Packit a4aae4
    void simple_print(ostream &out, string pad, Attr_iter i,
Packit a4aae4
                      bool dereference);
Packit a4aae4
Packit a4aae4
public:
Packit a4aae4
    AttrTable();
Packit a4aae4
    AttrTable(const AttrTable &rhs;;
Packit a4aae4
    virtual ~AttrTable();
Packit a4aae4
    AttrTable & operator=(const AttrTable &rhs;;
Packit a4aae4
Packit a4aae4
    virtual void erase();
Packit a4aae4
Packit a4aae4
    virtual unsigned int get_size() const;
Packit a4aae4
    virtual string get_name() const;
Packit a4aae4
    virtual void set_name(const string &n);
Packit a4aae4
Packit a4aae4
    /** Return a pointer to the AttrTable which holds this table (aka, its
Packit a4aae4
        parent. If this AttrTable has no parent, this returns null.
Packit a4aae4
        @return A pointer to the parent AttrTable. */
Packit a4aae4
    virtual AttrTable *get_parent() const
Packit a4aae4
    {
Packit a4aae4
        return d_parent;
Packit a4aae4
    }
Packit a4aae4
Packit a4aae4
    virtual bool is_global_attribute() const { return d_is_global_attribute; }
Packit a4aae4
    virtual void set_is_global_attribute(bool ga) { d_is_global_attribute = ga; }
Packit a4aae4
Packit a4aae4
    virtual unsigned int append_attr(const string &name, const string &type,
Packit a4aae4
				     const string &value);
Packit a4aae4
    virtual unsigned int append_attr(const string &name, const string &type,
Packit a4aae4
				     vector<string> *values);
Packit a4aae4
Packit a4aae4
    virtual AttrTable *append_container(const string &name);
Packit a4aae4
    virtual AttrTable *append_container(AttrTable *at, const string &name);
Packit a4aae4
Packit a4aae4
    virtual void find(const string &target, AttrTable **at, Attr_iter *iter);
Packit a4aae4
    virtual AttrTable *find_container(const string &target);
Packit a4aae4
    virtual AttrTable *recurrsive_find(const string &target,
Packit a4aae4
				       Attr_iter *location);
Packit a4aae4
Packit a4aae4
    Attr_iter simple_find(const string &target);
Packit a4aae4
    AttrTable *simple_find_container(const string &target);
Packit a4aae4
Packit a4aae4
Packit a4aae4
    virtual AttrTable *get_attr_table(const string &name);
Packit a4aae4
    virtual string get_type(const string &name);
Packit a4aae4
    virtual AttrType get_attr_type(const string &name);
Packit a4aae4
    virtual unsigned int get_attr_num(const string &name);
Packit a4aae4
    virtual string get_attr(const string &name, unsigned int i = 0);
Packit a4aae4
    virtual vector<string> *get_attr_vector(const string &name);
Packit a4aae4
    virtual void del_attr(const string &name, int i = -1);
Packit a4aae4
Packit a4aae4
    virtual Attr_iter attr_begin();
Packit a4aae4
    virtual Attr_iter attr_end();
Packit a4aae4
    virtual Attr_iter get_attr_iter(int i);
Packit a4aae4
    virtual string get_name(Attr_iter iter);
Packit a4aae4
    virtual bool is_container(Attr_iter iter);
Packit a4aae4
    virtual AttrTable *get_attr_table(Attr_iter iter);
Packit a4aae4
    virtual Attr_iter del_attr_table(Attr_iter iter);
Packit a4aae4
    virtual string get_type(Attr_iter iter);
Packit a4aae4
    virtual AttrType get_attr_type(Attr_iter iter);
Packit a4aae4
    virtual unsigned int get_attr_num(Attr_iter iter);
Packit a4aae4
    virtual string get_attr(Attr_iter iter, unsigned int i = 0);
Packit a4aae4
    virtual std::vector<string> *get_attr_vector(Attr_iter iter);
Packit a4aae4
    virtual bool is_global_attribute(Attr_iter iter);
Packit a4aae4
    virtual void set_is_global_attribute(Attr_iter iter, bool ga);
Packit a4aae4
Packit a4aae4
    virtual void add_container_alias(const string &name, AttrTable *src);
Packit a4aae4
    virtual void add_value_alias(AttrTable *at, const string &name,
Packit a4aae4
                         const string &source);
Packit a4aae4
    virtual bool attr_alias(const string &alias,
Packit a4aae4
			    AttrTable *at,
Packit a4aae4
			    const string &name);
Packit a4aae4
    virtual bool attr_alias(const string &alias, const string &name);
Packit a4aae4
Packit a4aae4
    virtual void print(FILE *out, string pad = "    ",
Packit a4aae4
		       bool dereference = false);
Packit a4aae4
    virtual void print(ostream &out, string pad = "    ",
Packit a4aae4
		       bool dereference = false);
Packit a4aae4
Packit a4aae4
    virtual void print_xml(FILE *out, string pad = "    ",
Packit a4aae4
			   bool constrained = false);
Packit a4aae4
    virtual void print_xml(ostream &out, string pad = "    ",
Packit a4aae4
			   bool constrained = false);
Packit a4aae4
Packit a4aae4
    void print_xml_writer(XMLWriter &xml;;
Packit a4aae4
Packit a4aae4
    void print_dap4(XMLWriter &xml;;
Packit a4aae4
Packit a4aae4
    virtual void dump(ostream &strm) const ;
Packit a4aae4
};
Packit a4aae4
Packit a4aae4
Packit a4aae4
string remove_space_encoding(const string &s);
Packit a4aae4
string add_space_encoding(const string &s);
Packit a4aae4
Packit a4aae4
} // namespace libdap
Packit a4aae4
Packit a4aae4
#endif // _attrtable_h