|
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 |
// jhrg 7/29/94
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <cassert>
|
|
Packit |
a4aae4 |
#include <sstream>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "AttrTable.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "util.h"
|
|
Packit |
a4aae4 |
#include "escaping.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "debug.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Should the www2id and id2www functions be used to encode attribute names?
|
|
Packit |
a4aae4 |
// Probably not... jhrg 11/16/11
|
|
Packit |
a4aae4 |
#define WWW_ENCODING 0
|
|
Packit |
a4aae4 |
// See the note for del_attr_table(). That method now deletes the contained
|
|
Packit |
a4aae4 |
// AttrTable.
|
|
Packit |
a4aae4 |
#define NEW_DEL_ATTR_TABLE_BEHAVIOR 0
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
using std::cerr;
|
|
Packit |
a4aae4 |
using std::string;
|
|
Packit |
a4aae4 |
using std::endl;
|
|
Packit |
a4aae4 |
using std::vector;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
namespace libdap {
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Remove %20 space encoding */
|
|
Packit |
a4aae4 |
string remove_space_encoding(const string &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type pos = s.find("%20");
|
|
Packit |
a4aae4 |
if (pos != string::npos) {
|
|
Packit |
a4aae4 |
string n = s;
|
|
Packit |
a4aae4 |
do {
|
|
Packit |
a4aae4 |
n.replace(pos, 3, " ");
|
|
Packit |
a4aae4 |
pos = n.find("%20");
|
|
Packit |
a4aae4 |
} while (pos != string::npos);
|
|
Packit |
a4aae4 |
return n;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return s;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Add %20 space encoding. */
|
|
Packit |
a4aae4 |
string add_space_encoding(const string &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type pos = s.find(" ");
|
|
Packit |
a4aae4 |
if (pos != string::npos) {
|
|
Packit |
a4aae4 |
string n = s;
|
|
Packit |
a4aae4 |
do {
|
|
Packit |
a4aae4 |
n.replace(pos, 1, "%20");
|
|
Packit |
a4aae4 |
pos = n.find(" ");
|
|
Packit |
a4aae4 |
} while (pos != string::npos);
|
|
Packit |
a4aae4 |
return n;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return s;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Convert an AttrType to it's string representation.
|
|
Packit |
a4aae4 |
@param at The Attribute Type.
|
|
Packit |
a4aae4 |
@return The type's string representation */
|
|
Packit |
a4aae4 |
string AttrType_to_String(const AttrType at)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
switch (at) {
|
|
Packit |
a4aae4 |
case Attr_container:
|
|
Packit |
a4aae4 |
return "Container";
|
|
Packit |
a4aae4 |
case Attr_byte:
|
|
Packit |
a4aae4 |
return "Byte";
|
|
Packit |
a4aae4 |
case Attr_int16:
|
|
Packit |
a4aae4 |
return "Int16";
|
|
Packit |
a4aae4 |
case Attr_uint16:
|
|
Packit |
a4aae4 |
return "UInt16";
|
|
Packit |
a4aae4 |
case Attr_int32:
|
|
Packit |
a4aae4 |
return "Int32";
|
|
Packit |
a4aae4 |
case Attr_uint32:
|
|
Packit |
a4aae4 |
return "UInt32";
|
|
Packit |
a4aae4 |
case Attr_float32:
|
|
Packit |
a4aae4 |
return "Float32";
|
|
Packit |
a4aae4 |
case Attr_float64:
|
|
Packit |
a4aae4 |
return "Float64";
|
|
Packit |
a4aae4 |
case Attr_string:
|
|
Packit |
a4aae4 |
return "String";
|
|
Packit |
a4aae4 |
case Attr_url:
|
|
Packit |
a4aae4 |
return "Url";
|
|
Packit |
a4aae4 |
case Attr_other_xml:
|
|
Packit |
a4aae4 |
return "OtherXML";
|
|
Packit |
a4aae4 |
default:
|
|
Packit |
a4aae4 |
return "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrType String_to_AttrType(const string &s)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string s2 = s;
|
|
Packit |
a4aae4 |
downcase(s2);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (s2 == "container")
|
|
Packit |
a4aae4 |
return Attr_container;
|
|
Packit |
a4aae4 |
else if (s2 == "byte")
|
|
Packit |
a4aae4 |
return Attr_byte;
|
|
Packit |
a4aae4 |
else if (s2 == "int16")
|
|
Packit |
a4aae4 |
return Attr_int16;
|
|
Packit |
a4aae4 |
else if (s2 == "uint16")
|
|
Packit |
a4aae4 |
return Attr_uint16;
|
|
Packit |
a4aae4 |
else if (s2 == "int32")
|
|
Packit |
a4aae4 |
return Attr_int32;
|
|
Packit |
a4aae4 |
else if (s2 == "uint32")
|
|
Packit |
a4aae4 |
return Attr_uint32;
|
|
Packit |
a4aae4 |
else if (s2 == "float32")
|
|
Packit |
a4aae4 |
return Attr_float32;
|
|
Packit |
a4aae4 |
else if (s2 == "float64")
|
|
Packit |
a4aae4 |
return Attr_float64;
|
|
Packit |
a4aae4 |
else if (s2 == "string")
|
|
Packit |
a4aae4 |
return Attr_string;
|
|
Packit |
a4aae4 |
else if (s2 == "url")
|
|
Packit |
a4aae4 |
return Attr_url;
|
|
Packit |
a4aae4 |
else if (s2 == "otherxml")
|
|
Packit |
a4aae4 |
return Attr_other_xml;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return Attr_unknown;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Clone the given attribute table in <tt>this</tt>.
|
|
Packit |
a4aae4 |
Protected. */
|
|
Packit |
a4aae4 |
void AttrTable::clone(const AttrTable &at)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
d_name = at.d_name;
|
|
Packit |
a4aae4 |
d_is_global_attribute = at.d_is_global_attribute;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Set the parent to null (no parent, not in container)
|
|
Packit |
a4aae4 |
// since using at.d_parent is semantically incorrect
|
|
Packit |
a4aae4 |
// and potentially dangerous.
|
|
Packit |
a4aae4 |
d_parent = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Attr_citer i = at.attr_map.begin();
|
|
Packit |
a4aae4 |
Attr_citer ie = at.attr_map.end();
|
|
Packit |
a4aae4 |
for (; i != ie; ++i) {
|
|
Packit |
a4aae4 |
// this deep-copies containers recursively
|
|
Packit |
a4aae4 |
entry *e = new entry(*(*i));
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If the entry being added was a container,
|
|
Packit |
a4aae4 |
// set its parent to this to maintain invariant.
|
|
Packit |
a4aae4 |
if (e->type == Attr_container) {
|
|
Packit |
a4aae4 |
assert(e->attributes);
|
|
Packit |
a4aae4 |
e->attributes->d_parent = this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @name Instance management functions */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
AttrTable::AttrTable() :
|
|
Packit |
a4aae4 |
DapObj(), d_name(""), d_parent(0), attr_map(), d_is_global_attribute(true)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable::AttrTable(const AttrTable &rhs) :
|
|
Packit |
a4aae4 |
DapObj()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
clone(rhs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Private
|
|
Packit |
a4aae4 |
void AttrTable::delete_attr_table()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
delete *i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
attr_map.clear();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable::~AttrTable()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
delete_attr_table();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable &
|
|
Packit |
a4aae4 |
AttrTable::operator=(const AttrTable &rhs)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (this != &rhs) {
|
|
Packit |
a4aae4 |
delete_attr_table();
|
|
Packit |
a4aae4 |
clone(rhs);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return *this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
//@}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Attributes that are containers count one attribute, as do
|
|
Packit |
a4aae4 |
attributes with both scalar and vector values.
|
|
Packit |
a4aae4 |
@return The number of entries.
|
|
Packit |
a4aae4 |
@brief Get the number of entries in this attribute table.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
unsigned int AttrTable::get_size() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return attr_map.size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Get the name of this attribute table.
|
|
Packit |
a4aae4 |
@return A string containing the name. */
|
|
Packit |
a4aae4 |
string AttrTable::get_name() const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return d_name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Set the name of this attribute table.
|
|
Packit |
a4aae4 |
@param n The new name of the attribute table. */
|
|
Packit |
a4aae4 |
void AttrTable::set_name(const string &n)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
d_name = www2id(n);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
d_name = remove_space_encoding(n);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// This was taken from das.y and could be used here to make the 'dods_errors'
|
|
Packit |
a4aae4 |
// attribute container like the parser used to. Then again, maybe this feature
|
|
Packit |
a4aae4 |
// was just BS. jhrg (ticket 1469)
|
|
Packit |
a4aae4 |
static void add_bad_attribute(AttrTable *attr, const string &type, const string &name, const string &value,
|
|
Packit |
a4aae4 |
const string &msg) {
|
|
Packit |
a4aae4 |
// First, if this bad value is already in a *_dods_errors container,
|
|
Packit |
a4aae4 |
// then just add it. This can happen when the server side processes a DAS
|
|
Packit |
a4aae4 |
// and then hands it off to a client which does the same.
|
|
Packit |
a4aae4 |
// Make a new container. Call it <attr's name>_errors. If that container
|
|
Packit |
a4aae4 |
// already exists, use it.
|
|
Packit |
a4aae4 |
// Add the attribute.
|
|
Packit |
a4aae4 |
// Add the error string to an attribute in the container called
|
|
Packit |
a4aae4 |
// `
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (attr->get_name().find("_dods_errors") != string::npos) {
|
|
Packit |
a4aae4 |
attr->append_attr(name, type, value);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
// I think _dods_errors should be _dap_error. jhrg 11/16/11
|
|
Packit |
a4aae4 |
string error_cont_name = attr->get_name() + "_dods_errors";
|
|
Packit |
a4aae4 |
AttrTable *error_cont = attr->get_attr_table(error_cont_name);
|
|
Packit |
a4aae4 |
if (!error_cont)
|
|
Packit |
a4aae4 |
error_cont = attr->append_container(error_cont_name);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
error_cont->append_attr(name, type, value);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifndef ATTR_STRING_QUOTE_FIX
|
|
Packit |
a4aae4 |
error_cont->append_attr(name + "_dap_explanation", "String", "\"" + msg + "\"");
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
error_cont->append_attr(name + "_dap_explanation", "String", msg);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** If the given name already refers to an attribute, and the attribute has a
|
|
Packit |
a4aae4 |
value, the given value is appended to the attribute vector. Calling this
|
|
Packit |
a4aae4 |
function repeatedly is the way to append to an attribute vector.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
The function throws an Error if the attribute is a container,
|
|
Packit |
a4aae4 |
or if the type of the input value does not match the existing attribute's
|
|
Packit |
a4aae4 |
type. Use <tt>append_container()</tt> to add container attributes.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This method performs a simple search for <tt>name</tt> in this attribute
|
|
Packit |
a4aae4 |
table only; sub-tables are not searched and the dot notation is not
|
|
Packit |
a4aae4 |
recognized.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add an attribute to the table.
|
|
Packit |
a4aae4 |
@return Returns the length of the added attribute value.
|
|
Packit |
a4aae4 |
@param name The name of the attribute to add or modify.
|
|
Packit |
a4aae4 |
@param type The type of the attribute to add or modify.
|
|
Packit |
a4aae4 |
@param value The value to add to the attribute table. */
|
|
Packit |
a4aae4 |
unsigned int AttrTable::append_attr(const string &name, const string &type, const string &value)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering AttrTable::append_attr" << endl);
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Attr_iter iter = simple_find(lname);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If the types don't match OR this attribute is a container, calling
|
|
Packit |
a4aae4 |
// this mfunc is an error!
|
|
Packit |
a4aae4 |
if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
|
|
Packit |
a4aae4 |
throw Error(string("An attribute called `") + name + string("' already exists but is of a different type"));
|
|
Packit |
a4aae4 |
if (iter != attr_map.end() && (get_type(iter) == "Container"))
|
|
Packit |
a4aae4 |
throw Error(string("An attribute called `") + name + string("' already exists but is a container."));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (iter != attr_map.end()) { // Must be a new attribute value; add it.
|
|
Packit |
a4aae4 |
(*iter)->attr->push_back(value);
|
|
Packit |
a4aae4 |
return (*iter)->attr->size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else { // Must be a completely new attribute; add it
|
|
Packit |
a4aae4 |
entry *e = new entry;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
e->name = lname;
|
|
Packit |
a4aae4 |
e->is_alias = false;
|
|
Packit |
a4aae4 |
e->type = String_to_AttrType(type); // Record type using standard names.
|
|
Packit |
a4aae4 |
e->attr = new vector<string> ;
|
|
Packit |
a4aae4 |
e->attr->push_back(value);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return e->attr->size(); // return the length of the attr vector
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This version of append_attr() takes a vector<string> of values.
|
|
Packit |
a4aae4 |
If the given name already refers to an attribute, and the attribute has
|
|
Packit |
a4aae4 |
values, append the new values to the existing ones.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
The function throws an Error if the attribute is a container,
|
|
Packit |
a4aae4 |
or if the type of the input value does not match the existing attribute's
|
|
Packit |
a4aae4 |
type. Use <tt>append_container()</tt> to add container attributes.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
This method performs a simple search for <tt>name</tt> in this attribute
|
|
Packit |
a4aae4 |
table only; sub-tables are not searched and the dot notation is not
|
|
Packit |
a4aae4 |
recognized.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add an attribute to the table.
|
|
Packit |
a4aae4 |
@return Returns the length of the added attribute value.
|
|
Packit |
a4aae4 |
@param name The name of the attribute to add or modify.
|
|
Packit |
a4aae4 |
@param type The type of the attribute to add or modify.
|
|
Packit |
a4aae4 |
@param values A vector of values. Note: The vector is COPIED, not stored. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
unsigned int AttrTable::append_attr(const string &name, const string &type, vector<string> *values)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
DBG(cerr << "Entering AttrTable::append_attr(..., vector)" << endl);
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
Attr_iter iter = simple_find(lname);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If the types don't match OR this attribute is a container, calling
|
|
Packit |
a4aae4 |
// this mfunc is an error!
|
|
Packit |
a4aae4 |
if (iter != attr_map.end() && ((*iter)->type != String_to_AttrType(type)))
|
|
Packit |
a4aae4 |
throw Error(string("An attribute called `") + name + string("' already exists but is of a different type"));
|
|
Packit |
a4aae4 |
if (iter != attr_map.end() && (get_type(iter) == "Container"))
|
|
Packit |
a4aae4 |
throw Error(string("An attribute called `") + name + string("' already exists but is a container."));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (iter != attr_map.end()) { // Must be new attribute values; add.
|
|
Packit |
a4aae4 |
vector<string>::iterator i = values->begin();
|
|
Packit |
a4aae4 |
while (i != values->end())
|
|
Packit |
a4aae4 |
(*iter)->attr->push_back(*i++);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return (*iter)->attr->size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else { // Must be a completely new attribute; add it
|
|
Packit |
a4aae4 |
entry *e = new entry;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
e->name = lname;
|
|
Packit |
a4aae4 |
e->is_alias = false;
|
|
Packit |
a4aae4 |
e->type = String_to_AttrType(type); // Record type using standard names.
|
|
Packit |
a4aae4 |
e->attr = new vector<string> (*values);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return e->attr->size(); // return the length of the attr vector
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Create and append an attribute container to this AttrTable. If this
|
|
Packit |
a4aae4 |
attribute table already contains an attribute container called
|
|
Packit |
a4aae4 |
<tt>name</tt> an exception is thrown. Return a pointer to the new container.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add a container to the attribute table.
|
|
Packit |
a4aae4 |
@param name The name of the container to create.
|
|
Packit |
a4aae4 |
@return A pointer to the new AttrTable object.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::append_container(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
AttrTable *new_at = new AttrTable;
|
|
Packit |
a4aae4 |
AttrTable *ret = NULL;
|
|
Packit |
a4aae4 |
try {
|
|
Packit |
a4aae4 |
ret = append_container(new_at, name);
|
|
Packit |
a4aae4 |
} catch (Error &e) {
|
|
Packit |
a4aae4 |
// an error occurred, attribute with that name already exists
|
|
Packit |
a4aae4 |
delete new_at;
|
|
Packit |
a4aae4 |
new_at = 0;
|
|
Packit |
a4aae4 |
throw;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return ret;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Append a new attribute container to this attribute table. The new
|
|
Packit |
a4aae4 |
container is <tt>at</tt> and its name is set to
|
|
Packit |
a4aae4 |
<tt>name</tt>. If this attribute
|
|
Packit |
a4aae4 |
table already contains an attribute container called
|
|
Packit |
a4aae4 |
<tt>name</tt> an exception is thrown.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note The value of \e name will override the name of \e at set using the
|
|
Packit |
a4aae4 |
set_name() method.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add a container to the attribute table.
|
|
Packit |
a4aae4 |
@param at A pointer to the new attribute table to append.
|
|
Packit |
a4aae4 |
@param name The name of the new attribute table.
|
|
Packit |
a4aae4 |
@return A pointer to the new AttrTable object.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::append_container(AttrTable *at, const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (simple_find(name) != attr_end())
|
|
Packit |
a4aae4 |
throw Error("There already exists a container called '" + name + "' in this attribute table (" + at->get_name() + "). (1)");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
DBG(cerr << "Setting appended attribute container name to: " << lname << endl);
|
|
Packit |
a4aae4 |
at->set_name(lname);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
entry *e = new entry;
|
|
Packit |
a4aae4 |
e->name = lname;
|
|
Packit |
a4aae4 |
e->is_alias = false;
|
|
Packit |
a4aae4 |
e->type = Attr_container;
|
|
Packit |
a4aae4 |
e->attributes = at;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
at->d_parent = this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return e->attributes;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Look for an attribute or an attribute container. If used to search
|
|
Packit |
a4aae4 |
for an attribute container, this method returns the container's \e
|
|
Packit |
a4aae4 |
parent using the value-result parameter \c at and a reference to the
|
|
Packit |
a4aae4 |
container using the iterator value-result parameter \c iter. If used
|
|
Packit |
a4aae4 |
to search for an attribute, the attribute's container is returned using
|
|
Packit |
a4aae4 |
\c at; the attribute itself can be accessed using the iterator \c iter.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param target The name (using dot notation) of the attribute or
|
|
Packit |
a4aae4 |
container to find.
|
|
Packit |
a4aae4 |
@param at A value-result used to return the attribute container in
|
|
Packit |
a4aae4 |
which \c target was found. Null if \c target was not found.
|
|
Packit |
a4aae4 |
@param iter The iterator which will reference the attribute found.
|
|
Packit |
a4aae4 |
Can be used to access \c target from within \c at. References
|
|
Packit |
a4aae4 |
dim_end() within \c at if the attribute or container does not exist. */
|
|
Packit |
a4aae4 |
void AttrTable::find(const string &target, AttrTable **at, Attr_iter *iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type dotpos = target.rfind('.');
|
|
Packit |
a4aae4 |
if (dotpos != string::npos) {
|
|
Packit |
a4aae4 |
string container = target.substr(0, dotpos);
|
|
Packit |
a4aae4 |
string field = target.substr(dotpos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
*at = find_container(container);
|
|
Packit |
a4aae4 |
if (*at) {
|
|
Packit |
a4aae4 |
*iter = (*at)->simple_find(field);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
*iter = attr_map.end();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
*at = recurrsive_find(target, iter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** This method scans for attributes using recursion to look inside containers
|
|
Packit |
a4aae4 |
even when the name of the attribute is not fully qualified. It starts
|
|
Packit |
a4aae4 |
looking in itself and descends into its children depth first. It will find
|
|
Packit |
a4aae4 |
attributes and attribute containers.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param target Look for the attribute with this name.
|
|
Packit |
a4aae4 |
@param location A value-result parameter. This returns an iterator to the
|
|
Packit |
a4aae4 |
attribute within the returned AttrTable object
|
|
Packit |
a4aae4 |
@return Returns a pointer to the AttrTable which holds \e target, or null
|
|
Packit |
a4aae4 |
if \e target is not found. In the latter case, the value of \e location is
|
|
Packit |
a4aae4 |
attr_end() for this AttrTable. */
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::recurrsive_find(const string &target, Attr_iter *location)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter i = attr_begin();
|
|
Packit |
a4aae4 |
while (i != attr_end()) {
|
|
Packit |
a4aae4 |
if (target == (*i)->name) {
|
|
Packit |
a4aae4 |
*location = i;
|
|
Packit |
a4aae4 |
return this;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if ((*i)->type == Attr_container) {
|
|
Packit |
a4aae4 |
AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
|
|
Packit |
a4aae4 |
if (at)
|
|
Packit |
a4aae4 |
return at;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
++i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
*location = i;
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
|
|
Packit |
a4aae4 |
/** Look in this AttrTable for the attribute called \c name. If found return
|
|
Packit |
a4aae4 |
an Attr_iter which references it, otherwise return the end iterator for
|
|
Packit |
a4aae4 |
this AttrTable.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param target The name of the attribute.
|
|
Packit |
a4aae4 |
@return An Attr_iter which references \c target. */
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter AttrTable::simple_find(const string &target)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter i;
|
|
Packit |
a4aae4 |
for (i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
if (target == (*i)->name) {
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Look in this attribute table for an attribute container named
|
|
Packit |
a4aae4 |
<tt>target</tt>. The search starts at this attribute table;
|
|
Packit |
a4aae4 |
<tt>target</tt> should
|
|
Packit |
a4aae4 |
use the dot notation to name containers held within children of this
|
|
Packit |
a4aae4 |
attribute table.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
To search the entire DAS object, make sure to invoke this method from
|
|
Packit |
a4aae4 |
that object.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Find an attribute with a given name.
|
|
Packit |
a4aae4 |
@param target The attribute container to find.
|
|
Packit |
a4aae4 |
@return A pointer to the attribute table or null if the container
|
|
Packit |
a4aae4 |
cannot be found. */
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::find_container(const string &target)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
string::size_type dotpos = target.find('.');
|
|
Packit |
a4aae4 |
if (dotpos != string::npos) {
|
|
Packit |
a4aae4 |
string container = target.substr(0, dotpos);
|
|
Packit |
a4aae4 |
string field = target.substr(dotpos + 1);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
AttrTable *at = simple_find_container(container);
|
|
Packit |
a4aae4 |
return (at) ? at->find_container(field) : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
return simple_find_container(target);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Made public for callers that want non-recursive find. [mjohnson 6 oct 09]
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::simple_find_container(const string &target)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (get_name() == target)
|
|
Packit |
a4aae4 |
return this;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
if (is_container(i) && target == (*i)->name) {
|
|
Packit |
a4aae4 |
return (*i)->attributes;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Each of the following accessors get information using the name of an
|
|
Packit |
a4aae4 |
attribute. They perform a simple search for the name in this
|
|
Packit |
a4aae4 |
attribute table only; sub-tables are not searched and the dot
|
|
Packit |
a4aae4 |
notation is not recognized.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@name Accessors using an attribute name */
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Get an attribute container. */
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::get_attr_table(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return find_container(name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Get the type name of an attribute within this attribute table. */
|
|
Packit |
a4aae4 |
string AttrTable::get_type(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter p = simple_find(name);
|
|
Packit |
a4aae4 |
return (p != attr_map.end()) ? get_type(p) : (string) "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief Get the type of an attribute.
|
|
Packit |
a4aae4 |
@return The <tt>AttrType</tt> value describing the attribute. */
|
|
Packit |
a4aae4 |
AttrType AttrTable::get_attr_type(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter p = simple_find(name);
|
|
Packit |
a4aae4 |
return (p != attr_map.end()) ? get_attr_type(p) : Attr_unknown;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** If the indicated attribute is a container attribute, this function
|
|
Packit |
a4aae4 |
returns the number of attributes in its attribute table. If the
|
|
Packit |
a4aae4 |
indicated attribute is not a container, the method returns the number
|
|
Packit |
a4aae4 |
of values for the attribute (1 for a scalar attribute, N for a vector
|
|
Packit |
a4aae4 |
attribute value).
|
|
Packit |
a4aae4 |
@brief Get the number of attributes in this container.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
unsigned int AttrTable::get_attr_num(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter iter = simple_find(name);
|
|
Packit |
a4aae4 |
return (iter != attr_map.end()) ? get_attr_num(iter) : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get a pointer to the vector of values associated with the attribute
|
|
Packit |
a4aae4 |
referenced by Pix <tt>p</tt> or named <tt>name</tt>.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Note that all values in an attribute table are stored as string data.
|
|
Packit |
a4aae4 |
They may be converted to a more appropriate internal format by the
|
|
Packit |
a4aae4 |
calling program.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@return If the indicated attribute is a container, this function
|
|
Packit |
a4aae4 |
returns the null pointer. Otherwise returns a pointer to the
|
|
Packit |
a4aae4 |
the attribute vector value.
|
|
Packit |
a4aae4 |
@brief Get a vector-valued attribute.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
vector<string> *
|
|
Packit |
a4aae4 |
AttrTable::get_attr_vector(const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter p = simple_find(name);
|
|
Packit |
a4aae4 |
return (p != attr_map.end()) ? get_attr_vector(p) : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Delete the attribute named <tt>name</tt>. If <tt>i</tt> is given, and
|
|
Packit |
a4aae4 |
the attribute has a vector value, delete the <tt>i</tt>$^th$
|
|
Packit |
a4aae4 |
element of the vector.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
You can use this function to delete container attributes, although
|
|
Packit |
a4aae4 |
the <tt>i</tt> parameter has no meaning for that operation.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Deletes an attribute.
|
|
Packit |
a4aae4 |
@param name The name of the attribute to delete. This can be an
|
|
Packit |
a4aae4 |
attribute of any type, including containers. However, this method
|
|
Packit |
a4aae4 |
looks only in this attribute table and does not recognize the dot
|
|
Packit |
a4aae4 |
notation.
|
|
Packit |
a4aae4 |
@param i If the named attribute is a vector, and <tt>i</tt> is
|
|
Packit |
a4aae4 |
non-negative, the i-th entry in the vector is deleted, and the
|
|
Packit |
a4aae4 |
array is repacked. If <tt>i</tt> equals -1 (the default), the
|
|
Packit |
a4aae4 |
entire attribute is deleted. */
|
|
Packit |
a4aae4 |
void AttrTable::del_attr(const string &name, int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Attr_iter iter = simple_find(lname);
|
|
Packit |
a4aae4 |
if (iter != attr_map.end()) {
|
|
Packit |
a4aae4 |
if (i == -1) { // Delete the whole attribute
|
|
Packit |
a4aae4 |
entry *e = *iter;
|
|
Packit |
a4aae4 |
attr_map.erase(iter);
|
|
Packit |
a4aae4 |
delete e;
|
|
Packit |
a4aae4 |
e = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else { // Delete one element from attribute array
|
|
Packit |
a4aae4 |
// Don't try to delete elements from the vector of values if the
|
|
Packit |
a4aae4 |
// map is a container!
|
|
Packit |
a4aae4 |
if ((*iter)->type == Attr_container)
|
|
Packit |
a4aae4 |
return;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*iter)->attr;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
assert(i >= 0 && i < (int) sxp->size());
|
|
Packit |
a4aae4 |
sxp->erase(sxp->begin() + i); // rm the element
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@} Accessors using an attribute name
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @name get information using an iterator */
|
|
Packit |
a4aae4 |
//@{
|
|
Packit |
a4aae4 |
/** Get an iterator to the first entry in this attribute table.
|
|
Packit |
a4aae4 |
@return Attr_iter; references the end of the array if empty list. */
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter AttrTable::attr_begin()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return attr_map.begin();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get an iterator to the end attribute table. Does not point to
|
|
Packit |
a4aae4 |
the last attribute in the table
|
|
Packit |
a4aae4 |
@return Attr_iter */
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter AttrTable::attr_end()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return attr_map.end();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Given an index \c i, return the \c Attr_iter to the corresponding
|
|
Packit |
a4aae4 |
element. This method provides a way to use all the methods that take an
|
|
Packit |
a4aae4 |
\c Attr_iter using a simple integer index. Use the get_attr_num() or
|
|
Packit |
a4aae4 |
get_size() methods to determine how many items the AttrTable contains.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param i The index
|
|
Packit |
a4aae4 |
@return The corresponding Attr_iter
|
|
Packit |
a4aae4 |
@see get_attr_num, get_size */
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter AttrTable::get_attr_iter(int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return attr_map.begin() + i;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the name of the attribute referenced by \e iter. */
|
|
Packit |
a4aae4 |
string AttrTable::get_name(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return (*iter)->name;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns true if the attribute referenced by \e i is a container. */
|
|
Packit |
a4aae4 |
bool AttrTable::is_container(Attr_iter i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return (*i)->type == Attr_container;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the attribute container referenced by \e iter. If no
|
|
Packit |
a4aae4 |
such container exists, then return a reference to the end of the
|
|
Packit |
a4aae4 |
table.
|
|
Packit |
a4aae4 |
@param iter Reference to a table contained by this object.
|
|
Packit |
a4aae4 |
@return The child attribute table. */
|
|
Packit |
a4aae4 |
AttrTable *
|
|
Packit |
a4aae4 |
AttrTable::get_attr_table(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
return (*iter)->type == Attr_container ? (*iter)->attributes : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Delete the iterator. Since AttrTable stores pointers to AttrTable
|
|
Packit |
a4aae4 |
objects, the caller should be sure to delete the AttrTable itself.
|
|
Packit |
a4aae4 |
The caller will gain control of the AttrTable* located at
|
|
Packit |
a4aae4 |
get_attr_table(iter) prior to this call.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note The original semantics of this methods were odd. The caller was
|
|
Packit |
a4aae4 |
responsible for deleting the AttrTable, but if they did that before calling
|
|
Packit |
a4aae4 |
this, then memory corruption would happen (because this code accesses a
|
|
Packit |
a4aae4 |
field of the table). If the caller did not delete the table, memory leaked.
|
|
Packit |
a4aae4 |
The only correct way to call the method was to grab the pointer, call this
|
|
Packit |
a4aae4 |
and then delete the pointer. I added a call to delete the contained
|
|
Packit |
a4aae4 |
AttrTable pointer, which changes the behavior of this, but probably in a
|
|
Packit |
a4aae4 |
way that will fix leaks in existing code. This change can be reverted by
|
|
Packit |
a4aae4 |
setting NEW_DEL_ATTR_TABLE_BEHAVIOR to false. jhrg 4/26/13
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@note calling this method invalidates the iterator \e iter.
|
|
Packit |
a4aae4 |
@param iter points to the entry to be deleted.
|
|
Packit |
a4aae4 |
@return The Attr_iter for the element following \e iter */
|
|
Packit |
a4aae4 |
AttrTable::Attr_iter AttrTable::del_attr_table(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if ((*iter)->type != Attr_container)
|
|
Packit |
a4aae4 |
return ++iter;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// the caller intends to delete/reuse the contained AttrTable,
|
|
Packit |
a4aae4 |
// so zero it out so it doesn't get deleted before we delete the entry
|
|
Packit |
a4aae4 |
// [mjohnson]
|
|
Packit |
a4aae4 |
struct entry *e = *iter;
|
|
Packit |
a4aae4 |
// container no longer has a parent.
|
|
Packit |
a4aae4 |
if (e->attributes) {
|
|
Packit |
a4aae4 |
e->attributes->d_parent = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if NEW_DEL_ATTR_TABLE_BEHAVIOR
|
|
Packit |
a4aae4 |
delete e->attributes;
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
e->attributes = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
delete e;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return attr_map.erase(iter);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the type name of an attribute referenced by \e iter.
|
|
Packit |
a4aae4 |
@param iter Reference to the Attribute.
|
|
Packit |
a4aae4 |
@return A string with the name of this attribute datatype. */
|
|
Packit |
a4aae4 |
string AttrTable::get_type(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
return AttrType_to_String((*iter)->type);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Get the type of the attribute referenced by \e iter.
|
|
Packit |
a4aae4 |
@param iter
|
|
Packit |
a4aae4 |
@return The datatype of this attribute in an instance of AttrType. */
|
|
Packit |
a4aae4 |
AttrType AttrTable::get_attr_type(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return (*iter)->type;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** If the attribute referenced by \e iter is a container attribute, this
|
|
Packit |
a4aae4 |
method returns the number of attributes in its attribute table.
|
|
Packit |
a4aae4 |
If the indicated attribute is not a container, the method returns the
|
|
Packit |
a4aae4 |
number of values for the attribute (1 for a scalar attribute, N for a
|
|
Packit |
a4aae4 |
vector attribute value).
|
|
Packit |
a4aae4 |
@param iter Reference to an attribute
|
|
Packit |
a4aae4 |
@return The number of elements in the attribute. */
|
|
Packit |
a4aae4 |
unsigned int AttrTable::get_attr_num(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
return ((*iter)->type == Attr_container) ? (*iter)->attributes->get_size() : (*iter)->attr->size();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns the value of an attribute. If the attribute has a vector
|
|
Packit |
a4aae4 |
value, you can indicate which is the desired value with the index
|
|
Packit |
a4aae4 |
argument, \e i. If the argument is omitted, the first value is
|
|
Packit |
a4aae4 |
returned. If the attribute has only a single value, the index
|
|
Packit |
a4aae4 |
argument is ignored. If \e i is greater than the number of
|
|
Packit |
a4aae4 |
elements in the attribute, an error is produced.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
All values in an attribute table are stored as string data. They may
|
|
Packit |
a4aae4 |
be converted to a more appropriate internal format by the calling
|
|
Packit |
a4aae4 |
program.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param iter Reference to an attribute
|
|
Packit |
a4aae4 |
@param i The attribute value index, zero-based. Default value: 0
|
|
Packit |
a4aae4 |
@return If the indicated attribute is a container, this function
|
|
Packit |
a4aae4 |
returns the string ``None''. If using a name to refer to the attribute
|
|
Packit |
a4aae4 |
and the named attribute does not exist, return the empty string. */
|
|
Packit |
a4aae4 |
string AttrTable::get_attr(Attr_iter iter, unsigned int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
return (*iter)->type == Attr_container ? (string) "None" : (*(*iter)->attr)[i];
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string AttrTable::get_attr(const string &name, unsigned int i)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
Attr_iter p = simple_find(name);
|
|
Packit |
a4aae4 |
return (p != attr_map.end()) ? get_attr(p, i) : (string) "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Returns a pointer to the vector of values associated with the
|
|
Packit |
a4aae4 |
attribute referenced by iterator \e iter.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Note that all values in an attribute table are stored as string data.
|
|
Packit |
a4aae4 |
They may be converted to a more appropriate internal format by the
|
|
Packit |
a4aae4 |
calling program.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param iter Reference to the Attribute.
|
|
Packit |
a4aae4 |
@return If the indicated attribute is a container, this function
|
|
Packit |
a4aae4 |
returns the null pointer. Otherwise returns a pointer to the
|
|
Packit |
a4aae4 |
the attribute vector value. */
|
|
Packit |
a4aae4 |
vector<string> *
|
|
Packit |
a4aae4 |
AttrTable::get_attr_vector(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
return (*iter)->type != Attr_container ? (*iter)->attr : 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
bool AttrTable::is_global_attribute(Attr_iter iter)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
if ((*iter)->type == Attr_container)
|
|
Packit |
a4aae4 |
return (*iter)->attributes->is_global_attribute();
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
return (*iter)->is_global;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void AttrTable::set_is_global_attribute(Attr_iter iter, bool ga)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
assert(iter != attr_map.end());
|
|
Packit |
a4aae4 |
if ((*iter)->type == Attr_container)
|
|
Packit |
a4aae4 |
(*iter)->attributes->set_is_global_attribute(ga);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
(*iter)->is_global = ga;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//@} Accessors that use an iterator
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Alias an attribute table. The alias should be added to this object.
|
|
Packit |
a4aae4 |
/** @brief Add an alias to a container held by this attribute table.
|
|
Packit |
a4aae4 |
@param name The name of the alias. May not use dot notation.
|
|
Packit |
a4aae4 |
@param src The existing attribute container to alias.
|
|
Packit |
a4aae4 |
@exception Error if an attribute, container or alias called
|
|
Packit |
a4aae4 |
<tt>name</tt> already exists in this attribute table. */
|
|
Packit |
a4aae4 |
void AttrTable::add_container_alias(const string &name, AttrTable *src)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (simple_find(lname) != attr_end())
|
|
Packit |
a4aae4 |
throw Error(string("There already exists a container called `") + name + string("in this attribute table. (2)"));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
entry *e = new entry;
|
|
Packit |
a4aae4 |
e->name = lname;
|
|
Packit |
a4aae4 |
e->is_alias = true;
|
|
Packit |
a4aae4 |
e->aliased_to = src->get_name();
|
|
Packit |
a4aae4 |
e->type = Attr_container;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
e->attributes = src;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Assume \e source names an attribute value in some container. Add an alias
|
|
Packit |
a4aae4 |
\e name for that value in this object.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Add an alias for an attribute.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param das
|
|
Packit |
a4aae4 |
@param name The name of the alias. May not use dot notation.
|
|
Packit |
a4aae4 |
@param source The name of the attribute to alias. May use dot
|
|
Packit |
a4aae4 |
notation.
|
|
Packit |
a4aae4 |
@exception Error if the attribute table already contains an
|
|
Packit |
a4aae4 |
attribute, container or alias called <tt>name</tt> or if an
|
|
Packit |
a4aae4 |
attribute called <tt>source</tt> does not exist. */
|
|
Packit |
a4aae4 |
void AttrTable::add_value_alias(AttrTable *das, const string &name, const string &source)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lname = www2id(name);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lname = remove_space_encoding(name);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
string lsource = www2id(source);
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
string lsource = remove_space_encoding(source);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// find the container that holds source and its (sources's) iterator
|
|
Packit |
a4aae4 |
// within that container. Search at the uppermost level of the attribute
|
|
Packit |
a4aae4 |
// object to find values defined `above' the current container.
|
|
Packit |
a4aae4 |
AttrTable *at;
|
|
Packit |
a4aae4 |
Attr_iter iter;
|
|
Packit |
a4aae4 |
das->find(lsource, &at, &iter);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If source is not found by looking at the topmost level, look in the
|
|
Packit |
a4aae4 |
// current table (i.e., alias z x where x is in the current container
|
|
Packit |
a4aae4 |
// won't be found by looking for `x' at the top level). See test case 26
|
|
Packit |
a4aae4 |
// in das-testsuite.
|
|
Packit |
a4aae4 |
if (!at || (iter == at->attr_end()) || !*iter) {
|
|
Packit |
a4aae4 |
find(lsource, &at, &iter);
|
|
Packit |
a4aae4 |
if (!at || (iter == at->attr_end()) || !*iter)
|
|
Packit |
a4aae4 |
throw Error(string("Could not find the attribute `") + source + string("' in the attribute object."));
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// If we've got a value to alias and it's being added at the top level of
|
|
Packit |
a4aae4 |
// the DAS, that's an error.
|
|
Packit |
a4aae4 |
if (at && !at->is_container(iter) && this == das)
|
|
Packit |
a4aae4 |
throw Error(
|
|
Packit |
a4aae4 |
string(
|
|
Packit |
a4aae4 |
"A value cannot be aliased to the top level of the DAS;\nOnly containers may be present at that level of the DAS."));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (simple_find(lname) != attr_end())
|
|
Packit |
a4aae4 |
throw Error(string("There already exists a container called `") + name + string("in this attribute table. (3)"));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
entry *e = new entry;
|
|
Packit |
a4aae4 |
e->name = lname;
|
|
Packit |
a4aae4 |
e->is_alias = true;
|
|
Packit |
a4aae4 |
e->aliased_to = lsource;
|
|
Packit |
a4aae4 |
e->type = get_attr_type(iter);
|
|
Packit |
a4aae4 |
if (at && e->type == Attr_container)
|
|
Packit |
a4aae4 |
e->attributes = at->get_attr_table(iter);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
e->attr = (*iter)->attr;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.push_back(e);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Deprecated
|
|
Packit |
a4aae4 |
/** Once an alias is
|
|
Packit |
a4aae4 |
inserted into an attribute table, reading the attributes for
|
|
Packit |
a4aae4 |
alias will return those stored for name.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
Two forms for this function exist: one searches for name
|
|
Packit |
a4aae4 |
in the AttrTable referenced by at while the other uses
|
|
Packit |
a4aae4 |
<tt>this</tt>. You can use <tt>DAS::get_attr_table()</tt> to
|
|
Packit |
a4aae4 |
get the attribute table for an arbitrary name.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Adds an alias to the set of attributes.
|
|
Packit |
a4aae4 |
@see get_attr_table
|
|
Packit |
a4aae4 |
@deprecated The current alias design is flawed. It is impossible to map
|
|
Packit |
a4aae4 |
this onto the XML implementation where the DAS and DDS information are
|
|
Packit |
a4aae4 |
combined in one object.
|
|
Packit |
a4aae4 |
@param alias The alias to insert into the attribute table.
|
|
Packit |
a4aae4 |
@param name The name of the already-existing attribute to which
|
|
Packit |
a4aae4 |
the alias will refer.
|
|
Packit |
a4aae4 |
@param at An attribute table in which to insert the alias. */
|
|
Packit |
a4aae4 |
bool AttrTable::attr_alias(const string &alias, AttrTable *at, const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
add_value_alias(at, alias, name);
|
|
Packit |
a4aae4 |
return true;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @deprecated The current alias design is flawed. It is impossible to map
|
|
Packit |
a4aae4 |
this onto the XML implementation where the DAS and DDS information are
|
|
Packit |
a4aae4 |
combined in one object.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@param alias The alias to insert into the attribute table.
|
|
Packit |
a4aae4 |
@param name The name of the already-existing attribute to which
|
|
Packit |
a4aae4 |
the alias will refer. */
|
|
Packit |
a4aae4 |
bool AttrTable::attr_alias(const string &alias, const string &name)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
return attr_alias(alias, this, name);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Erase the entire attribute table. This returns an AttrTable to the empty
|
|
Packit |
a4aae4 |
state that's the same as the object generated by the null constructor.
|
|
Packit |
a4aae4 |
@brief Erase the attribute table. */
|
|
Packit |
a4aae4 |
void AttrTable::erase()
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
delete *i;
|
|
Packit |
a4aae4 |
*i = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
attr_map.erase(attr_map.begin(), attr_map.end());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
d_name = "";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
const string double_quote = "\"";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// This is here as a result of the problem described in ticket #1163 where
|
|
Packit |
a4aae4 |
// the data handlers are adding quotes to string attributes so the DAS will
|
|
Packit |
a4aae4 |
// be printed correctly. But that has the affect of adding the quotes to the
|
|
Packit |
a4aae4 |
// attribute's _value_ not just it's print representation. As part of the fix
|
|
Packit |
a4aae4 |
// I made the code here add the quotes if the handlers are fixed (but not if
|
|
Packit |
a4aae4 |
// handlers are still adding them). The other part of 1163 is to fix all of
|
|
Packit |
a4aae4 |
// the handlers... What this fix means is that attributes whose values really
|
|
Packit |
a4aae4 |
// do contain bracketing quotes might be misunderstood, since we're assuming
|
|
Packit |
a4aae4 |
// those quotes were added by the handlers as a hack to get the output
|
|
Packit |
a4aae4 |
// formatting correct for the DAS. jhrg 7/30/08
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
static void write_string_attribute_for_das(ostream &out, const string &value, const string &term)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (is_quoted(value))
|
|
Packit |
a4aae4 |
out << value << term;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
out << double_quote << value << double_quote << term;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
static void
|
|
Packit |
a4aae4 |
write_string_attribute_for_das(FILE *out, const string &value, const string &term)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (is_quoted(value))
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s", value.c_str(), term.c_str());
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
fprintf(out, "\"%s\"%s", value.c_str(), term.c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
// Special treatment for XML: Make sure to escape double quotes when XML is
|
|
Packit |
a4aae4 |
// printed in a DAS.
|
|
Packit |
a4aae4 |
static void write_xml_attribute_for_das(ostream &out, const string &value, const string &term)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (is_quoted(value))
|
|
Packit |
a4aae4 |
out << escape_double_quotes(value) << term;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
out << double_quote << escape_double_quotes(value) << double_quote << term;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
static void
|
|
Packit |
a4aae4 |
write_xml_attribute_for_das(FILE *out, const string &value, const string &term)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (is_quoted(value))
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s", escape_double_quotes(value).c_str(), term.c_str());
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
fprintf(out, "\"%s\"%s", escape_double_quotes(value).c_str(), term.c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** A simple printer that does nothing fancy with aliases.
|
|
Packit |
a4aae4 |
Protected. */
|
|
Packit |
a4aae4 |
void AttrTable::simple_print(FILE *out, string pad, Attr_iter i, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
simple_print(oss, pad, i, dereference);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), 1, oss.str().length(), out);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
switch ((*i)->type) {
|
|
Packit |
a4aae4 |
case Attr_container:
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s {\n", pad.c_str(), id2www(get_name(i)).c_str());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s {\n", pad.c_str(), get_name(i).c_str());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
(*i)->attributes->print(out, pad + " ", dereference);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
fprintf(out, "%s}\n", pad.c_str());
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case Attr_string: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), id2www(get_name(i)).c_str());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), get_name(i).c_str());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
write_string_attribute_for_das(out, *i, ", ");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
write_string_attribute_for_das(out, *last, ";\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case Attr_other_xml: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), id2www(get_name(i)).c_str());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), get_name(i).c_str());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
write_xml_attribute_for_das(out, *i, ", ");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
write_xml_attribute_for_das(out, *last, ";\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), id2www(get_name(i)).c_str());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s %s ", pad.c_str(), get_type(i).c_str(), get_name(i).c_str());
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s", (*i).c_str(), ", ");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s", (*last).c_str(), ";\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** A simple printer that does nothing fancy with aliases.
|
|
Packit |
a4aae4 |
Protected. */
|
|
Packit |
a4aae4 |
void AttrTable::simple_print(ostream &out, string pad, Attr_iter i, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
switch ((*i)->type) {
|
|
Packit |
a4aae4 |
case Attr_container:
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
out << pad << id2www(get_name(i)) << " {\n";
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
out << pad << add_space_encoding(get_name(i)) << " {\n";
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
(*i)->attributes->print(out, pad + " ", dereference);
|
|
Packit |
a4aae4 |
out << pad << "}\n";
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case Attr_string: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << add_space_encoding(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
write_string_attribute_for_das(out, *i, ", ");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
write_string_attribute_for_das(out, *last, ";\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
case Attr_other_xml: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << add_space_encoding(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
write_xml_attribute_for_das(out, *i, ", ");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
write_xml_attribute_for_das(out, *last, ";\n");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
default: {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << id2www(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
out << pad << get_type(i) << " " << add_space_encoding(get_name(i)) << " ";
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
vector<string> *sxp = (*i)->attr;
|
|
Packit |
a4aae4 |
vector<string>::iterator last = sxp->end() - 1;
|
|
Packit |
a4aae4 |
for (vector<string>::iterator i = sxp->begin(); i != last; ++i) {
|
|
Packit |
a4aae4 |
out << *i << ", ";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
out << *last << ";\n";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
break;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Prints an ASCII representation of the attribute table to the
|
|
Packit |
a4aae4 |
indicated FILE pointer. The \c pad argument is prefixed to each
|
|
Packit |
a4aae4 |
line of the output to provide control of indentation.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Prints the attribute table.
|
|
Packit |
a4aae4 |
@param out Print to the given output FILE.
|
|
Packit |
a4aae4 |
@param pad Indent elements of a table using this string of spaces. By
|
|
Packit |
a4aae4 |
default this is a string of four spaces
|
|
Packit |
a4aae4 |
@param dereference If true, follow aliases. Default is false. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void AttrTable::print(FILE *out, string pad, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print(oss, pad, dereference);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), 1, oss.str().length(), out);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->is_alias) {
|
|
Packit |
a4aae4 |
if (dereference) {
|
|
Packit |
a4aae4 |
simple_print(out, pad, i, dereference);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
fprintf(out, "%sAlias %s %s;\n",
|
|
Packit |
a4aae4 |
pad.c_str(),
|
|
Packit |
a4aae4 |
id2www(get_name(i)).c_str(),
|
|
Packit |
a4aae4 |
id2www((*i)->aliased_to).c_str());
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
fprintf(out, "%sAlias %s %s;\n",
|
|
Packit |
a4aae4 |
pad.c_str(), add_space_encoding(get_name(i)).c_str(), add_space_encoding((*i)->aliased_to).c_str());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
simple_print(out, pad, i, dereference);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Prints an ASCII representation of the attribute table to the
|
|
Packit |
a4aae4 |
indicated output stream. The \c pad argument is prefixed to each
|
|
Packit |
a4aae4 |
line of the output to provide control of indentation.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
@brief Prints the attribute table.
|
|
Packit |
a4aae4 |
@param out Print to the given output stream.
|
|
Packit |
a4aae4 |
@param pad Indent elements of a table using this string of spaces. By
|
|
Packit |
a4aae4 |
default this is a string of four spaces
|
|
Packit |
a4aae4 |
@param dereference If true, follow aliases. Default is false. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void AttrTable::print(ostream &out, string pad, bool dereference)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->is_alias) {
|
|
Packit |
a4aae4 |
if (dereference) {
|
|
Packit |
a4aae4 |
simple_print(out, pad, i, dereference);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
#if WWW_ENCODING
|
|
Packit |
a4aae4 |
out << pad << "Alias " << id2www(get_name(i))
|
|
Packit |
a4aae4 |
<< " " << id2www((*i)->aliased_to) << ";\n";
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
out << pad << "Alias " << add_space_encoding(get_name(i)) << " "
|
|
Packit |
a4aae4 |
<< add_space_encoding((*i)->aliased_to) << ";\n";
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
simple_print(out, pad, i, dereference);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Print the attribute table in XML.
|
|
Packit |
a4aae4 |
@param out Destination
|
|
Packit |
a4aae4 |
@param pad Indent lines of text/xml this much. Default is four spaces.
|
|
Packit |
a4aae4 |
@param constrained Not used
|
|
Packit |
a4aae4 |
@deprecated */
|
|
Packit |
a4aae4 |
void AttrTable::print_xml(FILE *out, string pad, bool /*constrained*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
XMLWriter xml(pad);
|
|
Packit |
a4aae4 |
print_xml_writer(xml);
|
|
Packit |
a4aae4 |
fwrite(xml.get_doc(), sizeof(char), xml.get_doc_size(), out);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if OLD_XML_MOETHODS
|
|
Packit |
a4aae4 |
ostringstream oss;
|
|
Packit |
a4aae4 |
print_xml(oss, pad);
|
|
Packit |
a4aae4 |
fwrite(oss.str().data(), 1, oss.str().length(), out);
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
// Why this works: AttrTable is really a hacked class that used to
|
|
Packit |
a4aae4 |
// implement a single-level set of attributes. Containers
|
|
Packit |
a4aae4 |
// were added several years later by dropping in the 'entry' structure.
|
|
Packit |
a4aae4 |
// It's not a class in its own right; instead accessors from AttrTable
|
|
Packit |
a4aae4 |
// are used to access information from entry. So... the loop below
|
|
Packit |
a4aae4 |
// actually iterates over the entries of *this* (which is an instance of
|
|
Packit |
a4aae4 |
// AttrTable). A container is an entry whose sole value is an AttrTable
|
|
Packit |
a4aae4 |
// instance. 05/19/03 jhrg
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->is_alias) {
|
|
Packit |
a4aae4 |
fprintf(out, "%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
|
|
Packit |
a4aae4 |
pad.c_str(), id2xml(get_name(i)).c_str(),
|
|
Packit |
a4aae4 |
(*i)->aliased_to.c_str());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (is_container(i)) {
|
|
Packit |
a4aae4 |
fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
|
|
Packit |
a4aae4 |
pad.c_str(), id2xml(get_name(i)).c_str(),
|
|
Packit |
a4aae4 |
get_type(i).c_str());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
fprintf(out, "%s</Attribute>\n", pad.c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
fprintf(out, "%s<Attribute name=\"%s\" type=\"%s\">\n",
|
|
Packit |
a4aae4 |
pad.c_str(), id2xml(get_name(i)).c_str(), get_type(i).c_str());
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string value_pad = pad + " ";
|
|
Packit |
a4aae4 |
// Special handling for the OtherXML attribute type - don't escape
|
|
Packit |
a4aae4 |
// the XML and don't include the <value> element. Note that there
|
|
Packit |
a4aae4 |
// cannot be an vector of XML things as can be with the other types.
|
|
Packit |
a4aae4 |
if (get_attr_type(i) == Attr_other_xml) {
|
|
Packit |
a4aae4 |
if (get_attr_num(i) != 1)
|
|
Packit |
a4aae4 |
throw Error("OtherXML attributes cannot be vector-valued.");
|
|
Packit |
a4aae4 |
fprintf(out, "%s%s\n", value_pad.c_str(), get_attr(i, 0).c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
for (unsigned j = 0; j < get_attr_num(i); ++j) {
|
|
Packit |
a4aae4 |
fprintf(out, "%s<value>%s</value>\n", value_pad.c_str(),
|
|
Packit |
a4aae4 |
id2xml(get_attr(i, j)).c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
fprintf(out, "%s</Attribute>\n", pad.c_str());
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/**
|
|
Packit |
a4aae4 |
* @deprecated
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void AttrTable::print_xml(ostream &out, string pad, bool /*constrained*/)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
XMLWriter xml(pad);
|
|
Packit |
a4aae4 |
print_xml_writer(xml);
|
|
Packit |
a4aae4 |
out << xml.get_doc();
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->is_alias) {
|
|
Packit |
a4aae4 |
out << pad << "
|
|
Packit |
a4aae4 |
<< "\" Attribute=\"" << (*i)->aliased_to << "\"/>\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (is_container(i)) {
|
|
Packit |
a4aae4 |
out << pad << "
|
|
Packit |
a4aae4 |
<< "\" type=\"" << get_type(i) << "\">\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
get_attr_table(i)->print_xml(out, pad + " "/*, constrained*/);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
out << pad << "</Attribute>\n";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
out << pad << "
|
|
Packit |
a4aae4 |
<< "\" type=\"" << get_type(i) << "\">\n";
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
string value_pad = pad + " ";
|
|
Packit |
a4aae4 |
if (get_attr_type(i) == Attr_other_xml) {
|
|
Packit |
a4aae4 |
if (get_attr_num(i) != 1)
|
|
Packit |
a4aae4 |
throw Error("OtherXML attributes cannot be vector-valued.");
|
|
Packit |
a4aae4 |
out << value_pad << get_attr(i, 0) << "\n";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
string value_pad = pad + " ";
|
|
Packit |
a4aae4 |
for (unsigned j = 0; j < get_attr_num(i); ++j) {
|
|
Packit |
a4aae4 |
out << value_pad << "<value>" << id2xml(get_attr(i, j)) << "</value>\n";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
out << pad << "</Attribute>\n";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Print the attribute table in XML.
|
|
Packit |
a4aae4 |
@param out Destination stream
|
|
Packit |
a4aae4 |
@param pad Indent lines of text/xml this much. Default is four spaces.
|
|
Packit |
a4aae4 |
@param constrained Not used */
|
|
Packit |
a4aae4 |
void AttrTable::print_xml_writer(XMLWriter &xml)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
for (Attr_iter i = attr_begin(); i != attr_end(); ++i) {
|
|
Packit |
a4aae4 |
if ((*i)->is_alias) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Alias") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Alias element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_name(i).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "Attribute",
|
|
Packit |
a4aae4 |
(const xmlChar*) (*i)->aliased_to.c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end Alias element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (is_container(i)) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Attribute") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Attribute element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_name(i).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "type",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_type(i).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
get_attr_table(i)->print_xml_writer(xml);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end Attribute element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Attribute") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write Attribute element");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_name(i).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "type",
|
|
Packit |
a4aae4 |
(const xmlChar*) get_type(i).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (get_attr_type(i) == Attr_other_xml) {
|
|
Packit |
a4aae4 |
if (get_attr_num(i) != 1)
|
|
Packit |
a4aae4 |
throw Error("OtherXML attributes cannot be vector-valued.");
|
|
Packit |
a4aae4 |
// Replaced xmltextWriterWriteString with xmlTextWriterWriteRaw to keep the
|
|
Packit |
a4aae4 |
// libxml2 code from escaping the xml (which was breaking all of the inferencing
|
|
Packit |
a4aae4 |
// code. jhrg
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteRaw(xml.get_writer(), (const xmlChar*) get_attr(i, 0).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write OtherXML value");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
for (unsigned j = 0; j < get_attr_num(i); ++j) {
|
|
Packit |
a4aae4 |
if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "value") < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write value element");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterWriteString(xml.get_writer(), (const xmlChar*) get_attr(i, j).c_str()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not write attribute value");
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end value element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (xmlTextWriterEndElement(xml.get_writer()) < 0)
|
|
Packit |
a4aae4 |
throw InternalErr(__FILE__, __LINE__, "Could not end Attribute element");
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** Write the DAP4 XML representation for this attribute table. This
|
|
Packit |
a4aae4 |
* method is used to build the DAP4 DMR response object.
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param xml An XMLWriter that will do the serialization
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
AttrTable::print_dap4(XMLWriter &xml)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
print_xml_writer(xml);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/** @brief dumps information about this object
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* Displays the pointer value of this instance and all attributes stored
|
|
Packit |
a4aae4 |
*
|
|
Packit |
a4aae4 |
* @param strm C++ i/o stream to dump the information to
|
|
Packit |
a4aae4 |
* @return void
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
void AttrTable::dump(ostream &strm) const
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "AttrTable::dump - (" << (void *) this << ")" << endl;
|
|
Packit |
a4aae4 |
DapIndent::Indent();
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "table name: " << d_name << endl;
|
|
Packit |
a4aae4 |
if (attr_map.size()) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "attributes: " << endl;
|
|
Packit |
a4aae4 |
DapIndent::Indent();
|
|
Packit |
a4aae4 |
Attr_citer i = attr_map.begin();
|
|
Packit |
a4aae4 |
Attr_citer ie = attr_map.end();
|
|
Packit |
a4aae4 |
for (; i != ie; ++i) {
|
|
Packit |
a4aae4 |
entry *e = (*i);
|
|
Packit |
a4aae4 |
string type = AttrType_to_String(e->type);
|
|
Packit |
a4aae4 |
if (e->is_alias) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "alias: " << e->name << " aliased to: " << e->aliased_to << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (e->type == Attr_container) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "attr: " << e->name << " of type " << type << endl;
|
|
Packit |
a4aae4 |
DapIndent::Indent();
|
|
Packit |
a4aae4 |
e->attributes->dump(strm);
|
|
Packit |
a4aae4 |
DapIndent::UnIndent();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "attr: " << e->name << " of type " << type << endl;
|
|
Packit |
a4aae4 |
DapIndent::Indent();
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg;
|
|
Packit |
a4aae4 |
vector<string>::const_iterator iter = e->attr->begin();
|
|
Packit |
a4aae4 |
vector<string>::const_iterator last = e->attr->end() - 1;
|
|
Packit |
a4aae4 |
for (; iter != last; ++iter) {
|
|
Packit |
a4aae4 |
strm << (*iter) << ", ";
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
strm << (*(e->attr->end() - 1)) << endl;
|
|
Packit |
a4aae4 |
DapIndent::UnIndent();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
DapIndent::UnIndent();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "attributes: empty" << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (d_parent) {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "parent table:" << d_name << ":" << (void *) d_parent << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else {
|
|
Packit |
a4aae4 |
strm << DapIndent::LMarg << "parent table: none" << d_name << endl;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
DapIndent::UnIndent();
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
} // namespace libdap
|
|
Packit |
a4aae4 |
|