51#define NEW_DEL_ATTR_TABLE_BEHAVIOR 0
62 string::size_type pos = s.find(
"%20");
63 if (pos != string::npos) {
66 n.replace(pos, 3,
" ");
68 }
while (pos != string::npos);
77 string::size_type pos = s.find(
" ");
78 if (pos != string::npos) {
81 n.replace(pos, 1,
"%20");
83 }
while (pos != string::npos);
128 return "Enumeration";
140 if (s2 ==
"container")
142 else if (s2 ==
"byte")
144 else if (s2 ==
"int16")
146 else if (s2 ==
"uint16")
148 else if (s2 ==
"int32")
150 else if (s2 ==
"uint32")
152 else if (s2 ==
"float32")
154 else if (s2 ==
"float64")
156 else if (s2 ==
"string")
158 else if (s2 ==
"url")
160 else if (s2 ==
"otherxml")
164 else if (s2 ==
"int8")
166 else if (s2 ==
"uint8")
168 else if (s2 ==
"int64")
170 else if (s2 ==
"uint64")
172 else if (s2 ==
"enumeration")
174 else if (s2 ==
"opaque")
184 d_is_global_attribute = at.d_is_global_attribute;
193 for (; i != ie; ++i) {
196 attr_map.push_back(e);
215void AttrTable::delete_attr_table() {
216 for (
Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
259static void add_bad_attribute(
AttrTable *attr,
const string &type,
const string &name,
const string &value,
270 if (attr->
get_name().find(
"_dods_errors") != string::npos) {
275 string error_cont_name = attr->
get_name() +
"_dods_errors";
282#ifndef ATTR_STRING_QUOTE_FIX
283 error_cont->append_attr(name +
"_dap_explanation",
"String",
"\"" + msg +
"\"");
285 error_cont->append_attr(name +
"_dap_explanation",
"String", msg);
309 DBG(cerr <<
"Entering AttrTable::append_attr" << endl);
311 string lname =
www2id(name);
321 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
322 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
323 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
325 if (iter != attr_map.end()) {
326 (*iter)->attr->push_back(value);
327 return (*iter)->attr->size();
334 e->
attr =
new vector<string>;
335 e->
attr->push_back(value);
337 attr_map.push_back(e);
339 return e->
attr->size();
362 DBG(cerr <<
"Entering AttrTable::append_attr(..., vector)" << endl);
364 string lname =
www2id(name);
373 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
374 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
375 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
377 if (iter != attr_map.end()) {
379 while (i != values->end())
380 (*iter)->attr->push_back(*i++);
382 return (*iter)->attr->size();
389 e->
attr =
new vector<string>(*values);
391 attr_map.push_back(e);
393 return e->
attr->size();
416 DBG(cerr <<
"Entering AttrTable::append_attr" << endl);
418 string lname =
www2id(name);
428 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
429 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
430 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
432 if (iter != attr_map.end()) {
433 (*iter)->attr->push_back(value);
434 (*iter)->is_utf8_str = is_utf8_str;
435 return (*iter)->attr->size();
443 e->
attr =
new vector<string>;
444 e->
attr->push_back(value);
446 attr_map.push_back(e);
448 return e->
attr->size();
472 DBG(cerr <<
"Entering AttrTable::append_attr(..., vector)" << endl);
474 string lname =
www2id(name);
483 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is of a different type"));
484 if (iter != attr_map.end() && (
get_type(iter) ==
"Container"))
485 throw Error(
string(
"An attribute called `") + name +
string(
"' already exists but is a container."));
487 if (iter != attr_map.end()) {
489 while (i != values->end())
490 (*iter)->attr->push_back(*i++);
491 (*iter)->is_utf8_str = is_utf8_str;
492 return (*iter)->attr->size();
500 e->
attr =
new vector<string>(*values);
502 attr_map.push_back(e);
504 return e->
attr->size();
547 string lname =
www2id(name);
553 throw Error(
"There already exists a container called '" + name +
"' in this attribute table (" +
556 DBG(cerr <<
"Setting appended attribute container name to: " << lname << endl);
565 attr_map.push_back(e);
587 string::size_type dotpos = target.rfind(
'.');
588 if (dotpos != string::npos) {
589 string container = target.substr(0, dotpos);
590 string field = target.substr(dotpos + 1);
594 *iter = (*at)->simple_find(field);
596 *iter = attr_map.end();
617 if (target == (*i)->name) {
621 AttrTable *at = (*i)->attributes->recurrsive_find(target, location);
642 for (i = attr_map.begin(); i != attr_map.end(); ++i) {
643 if (target == (*i)->name) {
664 string::size_type dotpos = target.find(
'.');
665 if (dotpos != string::npos) {
666 string container = target.substr(0, dotpos);
667 string field = target.substr(dotpos + 1);
681 for (
Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
683 return (*i)->attributes;
704 return (p != attr_map.end()) ?
get_type(p) : (string)
"";
723 return (iter != attr_map.end()) ?
get_attr_num(iter) : 0;
761 string lname =
www2id(name);
767 if (iter != attr_map.end()) {
770 attr_map.erase(iter);
779 vector<string> *sxp = (*iter)->attr;
781 assert(i >= 0 && i < (
int)sxp->size());
782 sxp->erase(sxp->begin() + i);
812 assert(iter != attr_map.end());
814 return (*iter)->name;
826 assert(iter != attr_map.end());
855 struct entry *e = *iter;
860#if NEW_DEL_ATTR_TABLE_BEHAVIOR
868 return attr_map.erase(iter);
875 assert(iter != attr_map.end());
892 assert(iter != attr_map.end());
893 return ((*iter)->type ==
Attr_container) ? (*iter)->attributes->get_size() : (*iter)->attr->size();
913 assert(iter != attr_map.end());
915 return (*iter)->type ==
Attr_container ? (
string)
"None" : (*(*iter)->attr)[i];
920 return (p != attr_map.end()) ?
get_attr(p, i) : (string)
"";
935 assert(iter != attr_map.end());
940 assert(iter != attr_map.end());
942 return (*iter)->attributes->is_global_attribute();
944 return (*iter)->is_global;
948 assert(iter != attr_map.end());
950 (*iter)->attributes->set_is_global_attribute(ga);
952 (*iter)->is_global = ga;
965 string lname =
www2id(name);
971 throw Error(
string(
"There already exists a container called `") + name +
972 string(
"in this attribute table. (2)"));
982 attr_map.push_back(e);
999 string lname =
www2id(name);
1005 string lsource =
www2id(source);
1015 das->
find(lsource, &at, &iter);
1021 if (!at || (iter == at->
attr_end()) || !*iter) {
1022 find(lsource, &at, &iter);
1023 if (!at || (iter == at->
attr_end()) || !*iter)
1024 throw Error(
string(
"Could not find the attribute `") + source +
string(
"' in the attribute object."));
1030 throw Error(
string(
"A value cannot be aliased to the top level of the DAS;\nOnly containers may be present at "
1031 "that level of the DAS."));
1034 throw Error(
string(
"There already exists a container called `") + name +
1035 string(
"in this attribute table. (3)"));
1045 e->
attr = (*iter)->attr;
1047 attr_map.push_back(e);
1090 bool has_d4_attr =
false;
1091 for (
auto attr : attr_map) {
1092 string attr_fqn = path +
"@" + attr->name;
1093 bool isa_d4_attr = attr->
is_dap4_type(attr_fqn, inventory);
1097 has_d4_attr |= isa_d4_attr;
1106 for (
Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1111 attr_map.erase(attr_map.begin(), attr_map.end());
1129static void write_string_attribute_for_das(ostream &out,
const string &value,
const string &term,
bool is_utf8_str) {
1131 string esc_value = is_utf8_str ? value :
escattr(value);
1133 string esc_value =
escattr(value);
1139 out << esc_value << term;
1147write_string_attribute_for_das(FILE *out,
const string &value,
const string &term)
1150 fprintf(out,
"%s%s", value.c_str(), term.c_str());
1152 fprintf(out,
"\"%s\"%s", value.c_str(), term.c_str());
1158static void write_xml_attribute_for_das(ostream &out,
const string &value,
const string &term) {
1167write_xml_attribute_for_das(FILE *out,
const string &value,
const string &term)
1181 fwrite(oss.str().data(), 1, oss.str().length(), out);
1184 switch ((*i)->type) {
1187 fprintf(out,
"%s%s {\n", pad.c_str(),
id2www(
get_name(i)).c_str());
1189 fprintf(out,
"%s%s {\n", pad.c_str(),
get_name(i).c_str());
1191 (*i)->attributes->print(out, pad +
" ", dereference);
1193 fprintf(out,
"%s}\n", pad.c_str());
1200 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1202 vector<string> *sxp = (*i)->attr;
1205 write_string_attribute_for_das(out, *i,
", ");
1207 write_string_attribute_for_das(out, *last,
";\n");
1215 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1217 vector<string> *sxp = (*i)->attr;
1220 write_xml_attribute_for_das(out, *i,
", ");
1222 write_xml_attribute_for_das(out, *last,
";\n");
1230 fprintf(out,
"%s%s %s ", pad.c_str(),
get_type(i).c_str(),
get_name(i).c_str());
1233 vector<string> *sxp = (*i)->attr;
1236 fprintf(out,
"%s%s", (*i).c_str(),
", ");
1238 fprintf(out,
"%s%s", (*last).c_str(),
";\n");
1248 switch ((*i)->type) {
1255 (*i)->attributes->print(out, pad +
" ", dereference);
1256 out << pad <<
"}\n";
1265 vector<string> *sxp = (*i)->attr;
1269 write_string_attribute_for_das(out, *i_s,
", ", (*i)->is_utf8_str);
1271 write_string_attribute_for_das(out, *last,
";\n", (*i)->is_utf8_str);
1278 for (
const auto &attr:(*sxp)) {
1279 if (attr != (*sxp).back())
1280 write_string_attribute_for_das(out, attr,
", ",(*i)->is_utf8_str);
1282 write_string_attribute_for_das(out, attr,
";\n",(*i)->is_utf8_str);
1293 vector<string> *sxp = (*i)->attr;
1296 write_xml_attribute_for_das(out, *i,
", ");
1298 write_xml_attribute_for_das(out, *last,
";\n");
1307 vector<string> *sxp = (*i)->attr;
1312 out << *last <<
";\n";
1329 print(oss, pad, dereference);
1330 fwrite(oss.str().data(), 1, oss.str().length(), out);
1333 for (
Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1334 if ((*i)->is_alias) {
1340 fprintf(out,
"%sAlias %s %s;\n",
1343 id2www((*i)->aliased_to).c_str());
1345 fprintf(out,
"%sAlias %s %s;\n",
1369 for (
Attr_iter i = attr_map.begin(); i != attr_map.end(); ++i) {
1370 if ((*i)->is_alias) {
1400 fwrite(oss.str().data(), 1, oss.str().length(), out);
1413 if ((*i)->is_alias) {
1414 fprintf(out,
"%s<Alias name=\"%s\" Attribute=\"%s\"/>\n",
1416 (*i)->aliased_to.c_str());
1420 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1426 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1429 fprintf(out,
"%s<Attribute name=\"%s\" type=\"%s\">\n",
1432 string value_pad = pad +
" ";
1438 throw Error(
"OtherXML attributes cannot be vector-valued.");
1439 fprintf(out,
"%s%s\n", value_pad.c_str(),
get_attr(i, 0).c_str());
1443 fprintf(out,
"%s<value>%s</value>\n", value_pad.c_str(),
1447 fprintf(out,
"%s</Attribute>\n", pad.c_str());
1463 if ((*i)->is_alias) {
1465 <<
"\" Attribute=\"" << (*i)->aliased_to <<
"\"/>\n";
1470 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1474 out << pad <<
"</Attribute>\n";
1478 <<
"\" type=\"" <<
get_type(i) <<
"\">\n";
1480 string value_pad = pad +
" ";
1483 throw Error(
"OtherXML attributes cannot be vector-valued.");
1484 out << value_pad <<
get_attr(i, 0) <<
"\n";
1487 string value_pad = pad +
" ";
1489 out << value_pad <<
"<value>" <<
id2xml(
get_attr(i, j)) <<
"</value>\n";
1492 out << pad <<
"</Attribute>\n";
1504 if ((*i)->is_alias) {
1505 if (xmlTextWriterStartElement(xml.
get_writer(), (
const xmlChar *)
"Alias") < 0)
1506 throw InternalErr(__FILE__, __LINE__,
"Could not write Alias element");
1507 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"name",
1508 (
const xmlChar *)
get_name(i).c_str()) < 0)
1509 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1510 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"Attribute",
1511 (
const xmlChar *)(*i)->aliased_to.c_str()) < 0)
1512 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1513 if (xmlTextWriterEndElement(xml.
get_writer()) < 0)
1514 throw InternalErr(__FILE__, __LINE__,
"Could not end Alias element");
1516 if (xmlTextWriterStartElement(xml.
get_writer(), (
const xmlChar *)
"Attribute") < 0)
1517 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1518 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"name",
1519 (
const xmlChar *)
get_name(i).c_str()) < 0)
1520 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1521 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"type",
1522 (
const xmlChar *)
get_type(i).c_str()) < 0)
1523 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1527 if (xmlTextWriterEndElement(xml.
get_writer()) < 0)
1528 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1530 if (xmlTextWriterStartElement(xml.
get_writer(), (
const xmlChar *)
"Attribute") < 0)
1531 throw InternalErr(__FILE__, __LINE__,
"Could not write Attribute element");
1532 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"name",
1533 (
const xmlChar *)
get_name(i).c_str()) < 0)
1534 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1535 if (xmlTextWriterWriteAttribute(xml.
get_writer(), (
const xmlChar *)
"type",
1536 (
const xmlChar *)
get_type(i).c_str()) < 0)
1537 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
1541 throw Error(
"OtherXML attributes cannot be vector-valued.");
1545 if (xmlTextWriterWriteRaw(xml.
get_writer(), (
const xmlChar *)
get_attr(i, 0).c_str()) < 0)
1546 throw InternalErr(__FILE__, __LINE__,
"Could not write OtherXML value");
1553 if (xmlTextWriterStartElement(xml.
get_writer(), (
const xmlChar *)
"value") < 0)
1554 throw InternalErr(__FILE__, __LINE__,
"Could not write value element");
1557 if (xmlTextWriterWriteString(xml.
get_writer(), (
const xmlChar *)s.c_str()) < 0)
1558 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute value");
1560 if (xmlTextWriterEndElement(xml.
get_writer()) < 0)
1561 throw InternalErr(__FILE__, __LINE__,
"Could not end value element");
1565 if (xmlTextWriterStartElement(xml.
get_writer(), (
const xmlChar *)
"value") < 0)
1566 throw InternalErr(__FILE__, __LINE__,
"Could not write value element");
1568 if (xmlTextWriterWriteString(xml.
get_writer(), (
const xmlChar *)
get_attr(i, j).c_str()) < 0)
1569 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute value");
1571 if (xmlTextWriterEndElement(xml.
get_writer()) < 0)
1572 throw InternalErr(__FILE__, __LINE__,
"Could not end value element");
1575 if (xmlTextWriterEndElement(xml.
get_writer()) < 0)
1576 throw InternalErr(__FILE__, __LINE__,
"Could not end Attribute element");
1596 strm <<
DapIndent::LMarg <<
"AttrTable::dump - (" << (
void *)
this <<
")" << endl;
1599 if (attr_map.size()) {
1604 for (; i != ie; ++i) {
1620 for (; iter != last; ++iter) {
1621 strm << (*iter) <<
", ";
1623 strm << (*(e->
attr->end() - 1)) << endl;
1632 strm <<
DapIndent::LMarg <<
"parent table:" << d_name <<
":" << (
void *)d_parent << endl;
Contains the attributes for a dataset.
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
bool is_dap4_type(const std::string &path, std::vector< std::string > &inventory) const
void simple_print(FILE *out, string pad, Attr_iter i, bool dereference)
virtual unsigned int get_attr_num(const string &name)
Get the number of attributes in this container.
bool has_dap4_types(const std::string &path, std::vector< std::string > &inventory) const
virtual bool attr_alias(const string &alias, AttrTable *at, const string &name)
Adds an alias to the set of attributes.
virtual bool is_container(Attr_iter iter)
virtual void find(const string &target, AttrTable **at, Attr_iter *iter)
virtual void set_name(const string &n)
Set the name of this attribute table.
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
void clone(const AttrTable &at)
AttrTable & operator=(const AttrTable &rhs)
virtual Attr_iter attr_end()
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
virtual string get_attr(const string &name, unsigned int i=0)
AttrTable * simple_find_container(const string &target)
virtual string get_type(const string &name)
Get the type name of an attribute within this attribute table.
virtual bool is_global_attribute() const
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
virtual void add_value_alias(AttrTable *at, const string &name, const string &source)
Add an alias for an attribute.
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
virtual Attr_iter attr_begin()
virtual Attr_iter get_attr_iter(int i)
void print_dap4(XMLWriter &xml)
virtual void del_attr(const string &name, int i=-1)
Deletes an attribute.
virtual string get_name() const
Get the name of this attribute table.
virtual void erase()
Erase the attribute table.
virtual void set_is_global_attribute(bool ga)
void print_xml_writer(XMLWriter &xml)
virtual Attr_iter del_attr_table(Attr_iter iter)
virtual void print(FILE *out, string pad=" ", bool dereference=false)
Prints the attribute table.
virtual void add_container_alias(const string &name, AttrTable *src)
Add an alias to a container held by this attribute table.
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
virtual void dump(ostream &strm) const
dumps information about this object
std::vector< entry * >::const_iterator Attr_citer
virtual AttrTable * find_container(const string &target)
Find an attribute with a given name.
Attr_iter simple_find(const string &target)
std::vector< entry * >::iterator Attr_iter
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
virtual AttrTable * recurrsive_find(const string &target, Attr_iter *location)
static ostream & LMarg(ostream &strm)
libdap base object for common functionality of libdap objects
A class for error processing.
A class for software fault reporting.
unsigned int get_doc_size()
xmlTextWriterPtr get_writer() const
top level DAP object to house generic methods
string escattr_xml(string s)
string www2id(const string &in, const string &escape, const string &except)
string id2xml(string in, const string ¬_allowed)
string add_space_encoding(const string &s)
AttrType String_to_AttrType(const string &s)
string AttrType_to_String(const AttrType at)
const string double_quote
string escape_double_quotes(string source)
string remove_space_encoding(const string &s)
bool is_quoted(const string &s)
string id2www(string in, const string &allowable)
std::vector< string > * attr