libdap  Updated for version 3.20.10
libdap4 is an implementation of OPeNDAP's DAP protocol.
DDS.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // (c) COPYRIGHT URI/MIT 1994-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 //
32 // jhrg 9/7/94
33 
34 #include "config.h"
35 
36 #include <cstdio>
37 #include <cmath>
38 #include <climits>
39 //#include <cstdint>
40 
41 //#include <sys/types.h>
42 
43 #ifdef WIN32
44 #include <io.h>
45 #include <process.h>
46 #include <fstream>
47 #else
48 #include <unistd.h> // for alarm and dup
49 #include <sys/wait.h>
50 #endif
51 
52 #include <iostream>
53 #include <sstream>
54 #include <algorithm>
55 #include <functional>
56 #include <memory>
57 
58 // #define DODS_DEBUG
59 // #define DODS_DEBUG2
60 
61 #include "Byte.h"
62 #include "Int16.h"
63 #include "UInt16.h"
64 #include "Int32.h"
65 #include "UInt32.h"
66 #include "Float32.h"
67 #include "Float64.h"
68 #include "Str.h"
69 #include "Url.h"
70 #include "Array.h"
71 #include "Structure.h"
72 #include "Sequence.h"
73 #include "Grid.h"
74 
75 #include "DAS.h"
76 #include "Clause.h"
77 #include "Error.h"
78 #include "InternalErr.h"
79 #include "escaping.h"
80 #include "parser.h"
81 #include "debug.h"
82 #include "util.h"
83 #include "DapIndent.h"
84 
90 const string c_xml_xsi = "http://www.w3.org/2001/XMLSchema-instance";
91 const string c_xml_namespace = "http://www.w3.org/XML/1998/namespace";
92 
93 const string grddl_transformation_dap32 = "http://xml.opendap.org/transforms/ddxToRdfTriples.xsl";
94 
95 const string c_default_dap20_schema_location = "http://xml.opendap.org/dap/dap2.xsd";
96 const string c_default_dap32_schema_location = "http://xml.opendap.org/dap/dap3.2.xsd";
97 const string c_default_dap40_schema_location = "http://xml.opendap.org/dap/dap4.0.xsd";
98 
99 const string c_dap20_namespace = "http://xml.opendap.org/ns/DAP2";
100 const string c_dap32_namespace = "http://xml.opendap.org/ns/DAP/3.2#";
101 const string c_dap40_namespace = "http://xml.opendap.org/ns/DAP/4.0#";
102 
103 const string c_dap_20_n_sl = c_dap20_namespace + " " + c_default_dap20_schema_location;
104 const string c_dap_32_n_sl = c_dap32_namespace + " " + c_default_dap32_schema_location;
105 const string c_dap_40_n_sl = c_dap40_namespace + " " + c_default_dap40_schema_location;
106 
110 const string TOP_LEVEL_ATTRS_CONTAINER_NAME = "DAP4_GLOBAL";
111 
112 using namespace std;
113 
114 int ddsparse(libdap::parser_arg *arg);
115 
116 // Glue for the DDS parser defined in dds.lex
117 void dds_switch_to_buffer(void *new_buffer);
118 void dds_delete_buffer(void * buffer);
119 void *dds_buffer(FILE *fp);
120 
121 namespace libdap {
122 
123 void
124 DDS::duplicate(const DDS &dds)
125 {
126  DBG(cerr << "Entering DDS::duplicate... " <<endl);
127 
128  d_factory = dds.d_factory;
129 
130  d_name = dds.d_name;
131  d_filename = dds.d_filename;
132  d_container_name = dds.d_container_name;
133  d_container = dds.d_container;
134 
135  d_dap_major = dds.d_dap_major;
136  d_dap_minor = dds.d_dap_minor;
137 
138  d_dap_version = dds.d_dap_version; // String version of the protocol
139  d_request_xml_base = dds.d_request_xml_base;
140  d_namespace = dds.d_namespace;
141 
142  d_attr = dds.d_attr;
143 
144  DDS &dds_tmp = const_cast<DDS &>(dds);
145 
146  // copy the things pointed to by the list, not just the pointers
147  for (Vars_iter i = dds_tmp.var_begin(); i != dds_tmp.var_end(); i++) {
148  add_var(*i); // add_var() dups the BaseType.
149  }
150 
151  d_timeout = dds.d_timeout;
152 
153  d_max_response_size_kb = dds.d_max_response_size_kb;
154 }
155 
168 DDS::DDS(BaseTypeFactory *factory, const string &name)
169  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
170  d_request_xml_base(""),
171  d_timeout(0), /*d_keywords(),*/ d_max_response_size_kb(0)
172 {
173  DBG(cerr << "Building a DDS for the default version (2.0)" << endl);
174 
175  // This method sets a number of values, including those returned by
176  // get_protocol_major(), ..., get_namespace().
177  set_dap_version("2.0");
178 }
179 
195 DDS::DDS(BaseTypeFactory *factory, const string &name, const string &version)
196  : d_factory(factory), d_name(name), d_container_name(""), d_container(0),
197  d_request_xml_base(""),
198  d_timeout(0), /*d_keywords(),*/ d_max_response_size_kb(0)
199 {
200  DBG(cerr << "Building a DDS for version: " << version << endl);
201 
202  // This method sets a number of values, including those returned by
203  // get_protocol_major(), ..., get_namespace().
204  set_dap_version(version);
205 }
206 
208 DDS::DDS(const DDS &rhs) : DapObj()
209 {
210  DBG(cerr << "Entering DDS(const DDS &rhs) ..." << endl);
211  duplicate(rhs);
212  DBG(cerr << " bye." << endl);
213 }
214 
215 DDS::~DDS()
216 {
217  // delete all the variables in this DDS
218  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
219  BaseType *btp = *i ;
220  delete btp ; btp = 0;
221  }
222 }
223 
224 DDS &
225 DDS::operator=(const DDS &rhs)
226 {
227  if (this == &rhs)
228  return *this;
229  duplicate(rhs);
230  return *this;
231 }
232 
247 {
248  // If there is a container set in the DDS then check the container from
249  // the DAS. If they are not the same container, then throw an exception
250  // (should be working on the same container). If the container does not
251  // exist in the DAS, then throw an exception
252  if (d_container && das->container_name() != d_container_name)
253  throw InternalErr(__FILE__, __LINE__,
254  "Error transferring attributes: working on a container in dds, but not das");
255 
256  // Give each variable a chance to claim its attributes.
257  AttrTable *top = das->get_top_level_attributes();
258 
259  for (DDS::Vars_iter i = var_begin(), e = var_end(); i != e; i++) {
260  (*i)->transfer_attributes(top);
261  }
262 
263  // Now we transfer all the attributes still marked as global to the
264  // global container in the DDS.
265  for (AttrTable::Attr_iter i = top->attr_begin(), e = top->attr_end(); i != e; ++i) {
266  if ((*i)->type == Attr_container && (*i)->attributes->is_global_attribute()) {
267  // copy the source container so that the DAS passed in can be
268  // deleted after calling this method.
269  AttrTable *at = new AttrTable(*(*i)->attributes);
270  d_attr.append_container(at, at->get_name());
271  }
272  }
273 }
274 
282 
284 string
286 {
287  return d_name;
288 }
289 
291 void
292 DDS::set_dataset_name(const string &n)
293 {
294  d_name = n;
295 }
296 
298 
300 AttrTable &
302 {
303  return d_attr;
304 }
305 
315 string
317 {
318  return d_filename;
319 }
320 
322 void
323 DDS::filename(const string &fn)
324 {
325  d_filename = fn;
326 }
328 
332 void
334 {
335  d_dap_major = p;
336 
337  // This works because regardless of the order set_dap_major and set_dap_minor
338  // are called, once they both are called, the value in the string is
339  // correct. I protect against negative numbers because that would be
340  // nonsensical.
341  if (d_dap_minor >= 0) {
342  ostringstream oss;
343  oss << d_dap_major << "." << d_dap_minor;
344  d_dap_version = oss.str();
345  }
346 }
347 
351 void
353 {
354  d_dap_minor = p;
355 
356  if (d_dap_major >= 0) {
357  ostringstream oss;
358  oss << d_dap_major << "." << d_dap_minor;
359  d_dap_version = oss.str();
360  }
361 }
362 
368 void
369 DDS::set_dap_version(const string &v /* = "2.0" */)
370 {
371  istringstream iss(v);
372 
373  int major = -1, minor = -1;
374  char dot;
375  if (!iss.eof() && !iss.fail())
376  iss >> major;
377  if (!iss.eof() && !iss.fail())
378  iss >> dot;
379  if (!iss.eof() && !iss.fail())
380  iss >> minor;
381 
382  if (major == -1 || minor == -1 or dot != '.')
383  throw InternalErr(__FILE__, __LINE__, "Could not parse dap version. Value given: " + v);
384 
385  d_dap_version = v;
386 
387  d_dap_major = major;
388  d_dap_minor = minor;
389 
390  // Now set the related XML constants. These might be overwritten if
391  // the DDS instance is being built from a document parse, but if it's
392  // being constructed by a server the code to generate the XML document
393  // needs these values to match the DAP version information.
394  switch (d_dap_major) {
395  case 2:
396  d_namespace = c_dap20_namespace;
397  break;
398  case 3:
399  d_namespace = c_dap32_namespace;
400  break;
401  case 4:
402  d_namespace = c_dap40_namespace;
403  break;
404  default:
405  throw InternalErr(__FILE__, __LINE__, "Unknown DAP version.");
406  }
407 }
408 
416 void
418 {
419  int major = floor(d);
420  int minor = (d-major)*10;
421 
422  DBG(cerr << "Major: " << major << ", Minor: " << minor << endl);
423 
424  ostringstream oss;
425  oss << major << "." << minor;
426 
427  set_dap_version(oss.str());
428 }
429 
439 string
441 {
442  return d_container_name;
443 }
444 
447 void
448 DDS::container_name(const string &cn)
449 {
450  // we want to search the DDS for the top level structure with the given
451  // d_name. Set the container to null so that we don't search some previous
452  // container.
453  d_container = 0 ;
454  if( !cn.empty() )
455  {
456  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
457  if( !d_container )
458  {
459  // create a structure for this container. Calling add_var
460  // while_container is null will add the new structure to DDS and
461  // not some sub structure. Adding the new structure makes a copy
462  // of it. So after adding it, go get it and set d_container.
463  Structure *s = new Structure( cn ) ;
464  add_var( s ) ;
465  delete s ;
466  s = 0 ;
467  d_container = dynamic_cast<Structure *>( var( cn ) ) ;
468  }
469  }
470  d_container_name = cn;
471 
472 }
473 
475 Structure *
477 {
478  return d_container ;
479 }
480 
482 
494 //[[deprecated("Use DDS::get_request_size_kb()")]]
495 int DDS::get_request_size(bool constrained)
496 {
497  int w = 0;
498  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
499  if (constrained) {
500  if ((*i)->send_p())
501  w += (*i)->width(constrained);
502  }
503  else {
504  w += (*i)->width(constrained);
505  }
506  }
507  return w;
508 }
509 
522 uint64_t DDS::get_request_size_kb(bool constrained)
523 {
524  uint64_t req_size = 0;
525  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
526  if (constrained) {
527  if ((*i)->send_p())
528  req_size += (*i)->width(constrained);
529  }
530  else {
531  req_size += (*i)->width(constrained);
532  }
533  }
534  return req_size/1024;
535 }
536 
537 
544  if (!bt)
545  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
546 
547  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
548 
549  BaseType *btp = bt->ptr_duplicate();
550  DBG2(cerr << "In DDS::add_var(), btp's address is: " << btp << endl);
551  if (d_container) {
552  // Mem leak fix [mjohnson nov 2009]
553  // Structure::add_var() creates ANOTHER copy.
554  d_container->add_var(bt);
555  // So we need to delete btp or else it leaks
556  delete btp;
557  btp = 0;
558  }
559  else {
560  vars.push_back(btp);
561  }
562 }
563 
566 void
568 {
569  if (!bt)
570  throw InternalErr(__FILE__, __LINE__, "Trying to add a BaseType object with a NULL pointer.");
571 
572  DBG2(cerr << "In DDS::add_var(), bt's address is: " << bt << endl);
573 
574  if (d_container) {
575  d_container->add_var_nocopy(bt);
576  }
577  else {
578  vars.push_back(bt);
579  }
580 }
581 
588 void
589 DDS::del_var(const string &n)
590 {
591  if( d_container )
592  {
593  d_container->del_var( n ) ;
594  return ;
595  }
596 
597  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
598  if ((*i)->name() == n) {
599  BaseType *bt = *i ;
600  vars.erase(i) ;
601  delete bt ; bt = 0;
602  return;
603  }
604  }
605 }
606 
611 void
612 DDS::del_var(Vars_iter i)
613 {
614  if (i != vars.end()) {
615  BaseType *bt = *i ;
616  vars.erase(i) ;
617  delete bt ; bt = 0;
618  }
619 }
620 
627 void
628 DDS::del_var(Vars_iter i1, Vars_iter i2)
629 {
630  for (Vars_iter i_tmp = i1; i_tmp != i2; i_tmp++) {
631  BaseType *bt = *i_tmp ;
632  delete bt ; bt = 0;
633  }
634  vars.erase(i1, i2) ;
635 }
636 
644 BaseType *
645 DDS::var(const string &n, BaseType::btp_stack &s)
646 {
647  return var(n, &s);
648 }
649 
669 BaseType *
670 DDS::var(const string &n, BaseType::btp_stack *s)
671 {
672  string name = www2id(n);
673  if( d_container )
674  return d_container->var( name, false, s ) ;
675 
676  BaseType *v = exact_match(name, s);
677  if (v)
678  return v;
679 
680  return leaf_match(name, s);
681 }
682 
683 BaseType *
684 DDS::leaf_match(const string &n, BaseType::btp_stack *s)
685 {
686  DBG(cerr << "DDS::leaf_match: Looking for " << n << endl);
687 
688  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
689  BaseType *btp = *i;
690  DBG(cerr << "DDS::leaf_match: Looking for " << n << " in: " << btp->name() << endl);
691  // Look for the d_name in the dataset's top-level
692  if (btp->name() == n) {
693  DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
694  return btp;
695  }
696 
697  if (btp->is_constructor_type()) {
698  BaseType *found = btp->var(n, false, s);
699  if (found) {
700  DBG(cerr << "Found " << n << " in: " << btp->name() << endl);
701  return found;
702  }
703  }
704 #if STRUCTURE_ARRAY_SYNTAX_OLD
705  if (btp->is_vector_type() && btp->var()->is_constructor_type()) {
706  s->push(btp);
707  BaseType *found = btp->var()->var(n, false, s);
708  if (found) {
709  DBG(cerr << "Found " << n << " in: " << btp->var()->d_name() << endl);
710  return found;
711  }
712  }
713 #endif
714  }
715 
716  return 0; // It is not here.
717 }
718 
719 BaseType *
720 DDS::exact_match(const string &name, BaseType::btp_stack *s)
721 {
722  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
723  BaseType *btp = *i;
724  DBG2(cerr << "Looking for " << d_name << " in: " << btp << endl);
725  // Look for the d_name in the current ctor type or the top level
726  if (btp->name() == name) {
727  DBG2(cerr << "Found " << d_name << " in: " << btp << endl);
728  return btp;
729  }
730  }
731 
732  string::size_type dot_pos = name.find(".");
733  if (dot_pos != string::npos) {
734  string aggregate = name.substr(0, dot_pos);
735  string field = name.substr(dot_pos + 1);
736 
737  BaseType *agg_ptr = var(aggregate, s);
738  if (agg_ptr) {
739  DBG2(cerr << "Descending into " << agg_ptr->name() << endl);
740  return agg_ptr->var(field, true, s);
741  }
742  else
743  return 0; // qualified names must be *fully* qualified
744  }
745 
746  return 0; // It is not here.
747 }
748 
753 void
754 DDS::insert_var(Vars_iter i, BaseType *ptr)
755 {
756  vars.insert(i, ptr->ptr_duplicate());
757 }
758 
766 void
768 {
769  vars.insert(i, ptr);
770 }
771 
773 int
775 {
776  return vars.size();
777 }
778 
779 void
780 DDS::timeout_on()
781 {
782 #if USE_LOCAL_TIMEOUT_SCHEME
783 #ifndef WIN32
784  alarm(d_timeout);
785 #endif
786 #endif
787 }
788 
789 void
790 DDS::timeout_off()
791 {
792 #if USE_LOCAL_TIMEOUT_SCHEME
793 #ifndef WIN32
794  // Old behavior commented out. I think it is an error to change the value
795  // of d_timeout. The way this will likely be used is to set the timeout
796  // value once and then 'turn on' or turn off' that timeout as the situation
797  // dictates. The initeded use for the DDS timeout is so that timeouts for
798  // data responses will include the CPU resources needed to build the response
799  // but not the time spent transmitting the response. This may change when
800  // more parallelism is added to the server... These methods are called from
801  // BESDapResponseBuilder in bes/dap. jhrg 12/22/15
802 
803  // d_timeout = alarm(0);
804 
805  alarm(0);
806 #endif
807 #endif
808 }
809 
810 void
811 DDS::set_timeout(int)
812 {
813 #if USE_LOCAL_TIMEOUT_SCHEME
814  // Has no effect under win32
815  d_timeout = t;
816 #endif
817 }
818 
819 int
820 DDS::get_timeout()
821 {
822 #if USE_LOCAL_TIMEOUT_SCHEME
823  // Has to effect under win32
824  return d_timeout;
825 #endif
826  return 0;
827 }
828 
830 void
832 {
833  for (Vars_iter i = vars.begin(); i != vars.end(); i++) {
834  if ((*i)->type() == dods_sequence_c)
835  dynamic_cast<Sequence&>(**i).set_leaf_sequence();
836  else if ((*i)->type() == dods_structure_c)
837  dynamic_cast<Structure&>(**i).set_leaf_sequence();
838  }
839 }
840 
842 void
843 DDS::parse(string fname)
844 {
845  FILE *in = fopen(fname.c_str(), "r");
846 
847  if (!in) {
848  throw Error(cannot_read_file, "Could not open: " + fname);
849  }
850 
851  try {
852  parse(in);
853  fclose(in);
854  }
855  catch (Error &e) {
856  fclose(in);
857  throw ;
858  }
859 }
860 
861 
863 void
864 DDS::parse(int fd)
865 {
866 #ifdef WIN32
867  int new_fd = _dup(fd);
868 #else
869  int new_fd = dup(fd);
870 #endif
871 
872  if (new_fd < 0)
873  throw InternalErr(__FILE__, __LINE__, "Could not access file.");
874  FILE *in = fdopen(new_fd, "r");
875 
876  if (!in) {
877  throw InternalErr(__FILE__, __LINE__, "Could not access file.");
878  }
879 
880  try {
881  parse(in);
882  fclose(in);
883  }
884  catch (Error &e) {
885  fclose(in);
886  throw ;
887  }
888 }
889 
896 void
897 DDS::parse(FILE *in)
898 {
899  if (!in) {
900  throw InternalErr(__FILE__, __LINE__, "Null input stream.");
901  }
902 
903  void *buffer = dds_buffer(in);
904  dds_switch_to_buffer(buffer);
905 
906  parser_arg arg(this);
907 
908  bool status = ddsparse(&arg) == 0;
909 
910  dds_delete_buffer(buffer);
911 
912  DBG2(cout << "Status from parser: " << status << endl);
913 
914  // STATUS is the result of the parser function; if a recoverable error
915  // was found it will be true but arg.status() will be false.
916  if (!status || !arg.status()) {// Check parse result
917  if (arg.error())
918  throw *arg.error();
919  }
920 }
921 
923 void
924 DDS::print(FILE *out)
925 {
926  ostringstream oss;
927  print(oss);
928  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
929 }
930 
932 void
933 DDS::print(ostream &out)
934 {
935  out << "Dataset {\n" ;
936 
937  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
938  (*i)->print_decl(out) ;
939  }
940 
941  out << "} " << id2www(d_name) << ";\n" ;
942 
943  return ;
944 }
945 
953 bool
955 {
956  for (AttrTable::Attr_iter i = a.attr_begin(), e = a.attr_end(); i != e; ++i) {
957  if (a.get_attr_type(i) != Attr_container) {
958  return true;
959  }
960  else if (has_dap2_attributes(*a.get_attr_table(i))) {
961  return true;
962  }
963  }
964 
965  return false;
966 }
967 
975 bool
977 {
978  if (btp->get_attr_table().get_size() && has_dap2_attributes(btp->get_attr_table())) {
979  return true;
980  }
981 
982  Constructor *cons = dynamic_cast<Constructor *>(btp);
983  if (cons) {
984  Grid* grid = dynamic_cast<Grid*>(btp);
985  if(grid){
986  return has_dap2_attributes(grid->get_array());
987  }
988  else {
989  for (Constructor::Vars_iter i = cons->var_begin(), e = cons->var_end(); i != e; i++) {
990  if (has_dap2_attributes(*i)) return true;
991  }
992  }
993  }
994  return false;
995 }
996 
1006 static string four_spaces = " ";
1007 void print_var_das(ostream &out, BaseType *bt, string indent = "") {
1008 
1009  if (!has_dap2_attributes(bt))
1010  return;
1011 
1012  AttrTable attr_table = bt->get_attr_table();
1013  out << indent << add_space_encoding(bt->name()) << " {" << endl;
1014 
1015  Constructor *cnstrctr = dynamic_cast<Constructor *>(bt);
1016  if (cnstrctr) {
1017  Grid *grid = dynamic_cast<Grid *>(bt);
1018  if (grid) {
1019  Array *gridArray = grid->get_array();
1020  AttrTable arrayAT = gridArray->get_attr_table();
1021 
1022  if (has_dap2_attributes(gridArray))
1023  gridArray->get_attr_table().print(out, indent + four_spaces);
1024 #if 0
1025  // I dropped this because we don't want the MAP vectors showing up in the DAS
1026  // as children of a Grid (aka flatten the Grid bro) - ndp 5/25/18
1027  for (Grid::Map_iter mIter = grid->map_begin();
1028  mIter != grid->map_end(); ++mIter) {
1029  BaseType *currentMap = *mIter;
1030  if (has_dap2_attributes(currentMap))
1031  print_var_das(out, currentMap, indent + four_spaces);
1032  }
1033 #endif
1034  }
1035  else {
1036  attr_table.print(out, indent + four_spaces);
1037  Constructor::Vars_iter i = cnstrctr->var_begin();
1038  Constructor::Vars_iter e = cnstrctr->var_end();
1039  for (; i != e; i++) {
1040  // Only call print_var_das() if there really are attributes.
1041  // This is made complicated because while there might be none
1042  // for a particular var (*i), that var might be a ctor and its
1043  // descendant might have an attribute. jhrg 3/18/18
1044  if (has_dap2_attributes(*i))
1045  print_var_das(out, *i, indent + four_spaces);
1046  }
1047  }
1048  }
1049  else {
1050  attr_table.print(out, indent + four_spaces);
1051  }
1052 
1053  out << indent << "}" << endl;
1054 }
1055 
1064 void
1065 DDS::print_das(ostream &out)
1066 {
1067  unique_ptr<DAS> das(get_das());
1068 
1069  das->print(out);
1070 }
1071 
1081 DAS *
1083 {
1084  DAS *das = new DAS();
1085  get_das(das);
1086  return das;
1087 }
1088 
1094 static string
1095 get_unique_top_level_global_container_name(DAS *das)
1096 {
1097  // It's virtually certain that the TOP_LEVE... name will be unique. If so,
1098  // return the name. The code tests for a table to see if the name _should not_ be used.
1099  AttrTable *table = das->get_table(TOP_LEVEL_ATTRS_CONTAINER_NAME);
1100  if (!table)
1101  return TOP_LEVEL_ATTRS_CONTAINER_NAME;
1102 
1103  // ... but the default name might already be used
1104  unsigned int i = 0;
1105  string name;
1106  ostringstream oss;
1107  while (table) {
1108  oss.str(""); // reset to empty for the next suffix
1109  oss << "_" << ++i;
1110  if (!(i < UINT_MAX))
1111  throw InternalErr(__FILE__, __LINE__, "Cannot add top-level attributes to the DAS");
1112  name = TOP_LEVEL_ATTRS_CONTAINER_NAME + oss.str();
1113  table = das->get_table(name);
1114  }
1115 
1116  return name;
1117 }
1118 
1127  Constructor *cons = dynamic_cast<Constructor *>(bt);
1128  if (cons) {
1129  Grid *grid = dynamic_cast<Grid *>(bt);
1130  if(grid){
1131  Array *gridArray = grid->get_array();
1132  AttrTable arrayAT = gridArray->get_attr_table();
1133 
1134  for( AttrTable::Attr_iter atIter = arrayAT.attr_begin(); atIter!=arrayAT.attr_end(); ++atIter){
1135  AttrType type = arrayAT.get_attr_type(atIter);
1136  string childName = arrayAT.get_name(atIter);
1137  if (type == Attr_container){
1138  at->append_container( new AttrTable(*arrayAT.get_attr_table(atIter)), childName);
1139  }
1140  else {
1141  vector<string>* pAttrTokens = arrayAT.get_attr_vector(atIter);
1142  // append_attr makes a copy of the vector, so we don't have to do so here.
1143  at->append_attr(childName, AttrType_to_String(type), pAttrTokens);
1144  }
1145  }
1146 
1147  }
1148  else {
1149  for (Constructor::Vars_iter i = cons->var_begin(), e = cons->var_end(); i != e; i++) {
1150  if (has_dap2_attributes(*i)) {
1151  AttrTable *childAttrT = new AttrTable((*i)->get_attr_table());
1152  fillConstructorAttrTable(childAttrT, *i);
1153  at->append_container(childAttrT,(*i)->name());
1154  }
1155  }
1156  }
1157  }
1158 }
1159 
1160 void DDS::get_das(DAS *das)
1161 {
1162  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1163  if (has_dap2_attributes(*i)) {
1164  AttrTable *childAttrT = new AttrTable((*i)->get_attr_table());
1165  fillConstructorAttrTable(childAttrT, *i);
1166  das->add_table((*i)->name(), childAttrT);
1167  }
1168  }
1169 
1170  // Used in the rare case we have global attributes not in a table.
1171  unique_ptr<AttrTable> global(new AttrTable);
1172 
1173  for (AttrTable::Attr_iter i = d_attr.attr_begin(); i != d_attr.attr_end(); ++i) {
1174  // It's possible, given the API and if the DDS was built from a DMR, that a
1175  // global attribute might not be a container; check for that.
1176  if (d_attr.get_attr_table(i)) {
1177  das->add_table(d_attr.get_name(i), new AttrTable(*(d_attr.get_attr_table(i))));
1178  }
1179  else {
1180  // This must be a top level attribute outside a container. jhrg 4/6/18
1181  global->append_attr(d_attr.get_name(i), d_attr.get_type(i), d_attr.get_attr_vector(i));
1182  }
1183  }
1184 
1185  // if any attributes were added to 'global,' add it to the DAS and take control of the pointer.
1186  if (global->get_size() > 0) {
1187  das->add_table(get_unique_top_level_global_container_name(das), global.get()); // What if this name is not unique?
1188  global.release();
1189  }
1190 }
1191 
1202 void
1204 {
1205  ostringstream oss;
1206  print_constrained(oss);
1207  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
1208 }
1209 
1220 void
1222 {
1223  out << "Dataset {\n" ;
1224 
1225  for (Vars_citer i = vars.begin(); i != vars.end(); i++) {
1226  // for each variable, indent with four spaces, print a trailing
1227  // semicolon, do not print debugging information, print only
1228  // variables in the current projection.
1229  (*i)->print_decl(out, " ", true, false, true) ;
1230  }
1231 
1232  out << "} " << id2www(d_name) << ";\n" ;
1233 
1234  return;
1235 }
1236 
1248 void
1249 DDS::print_xml(FILE *out, bool constrained, const string &blob)
1250 {
1251  ostringstream oss;
1252  print_xml_writer(oss, constrained, blob);
1253  fwrite(oss.str().data(), 1, oss.str().length(), out);
1254 }
1255 
1267 void
1268 DDS::print_xml(ostream &out, bool constrained, const string &blob)
1269 {
1270  print_xml_writer(out, constrained, blob);
1271 }
1272 
1273 class VariablePrintXMLWriter : public unary_function<BaseType *, void>
1274 {
1275  XMLWriter &d_xml;
1276  bool d_constrained;
1277 public:
1278  VariablePrintXMLWriter(XMLWriter &xml, bool constrained)
1279  : d_xml(xml), d_constrained(constrained)
1280  {}
1281  void operator()(BaseType *bt)
1282  {
1283  bt->print_xml_writer(d_xml, d_constrained);
1284  }
1285 };
1286 
1303 void
1304 DDS::print_xml_writer(ostream &out, bool constrained, const string &blob)
1305 {
1306  XMLWriter xml(" ");
1307 
1308  // This is the 'DAP 3.2' DDX response - now the only response libdap will return.
1309  // jhrg 9/10/18
1310  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dataset") < 0)
1311  throw InternalErr(__FILE__, __LINE__, "Could not write Dataset element");
1312  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
1313  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1314  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*)"http://www.w3.org/2001/XMLSchema-instance") < 0)
1315  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1316 
1317  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation", (const xmlChar*)c_dap_32_n_sl.c_str()) < 0)
1318  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1319 
1320  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:grddl", (const xmlChar*)"http://www.w3.org/2003/g/data-view#") < 0)
1321  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:grddl");
1322 
1323  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "grddl:transformation", (const xmlChar*)grddl_transformation_dap32.c_str()) < 0)
1324  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:transformation");
1325 
1326  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1327  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1328  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:dap", (const xmlChar*)c_dap32_namespace.c_str()) < 0)
1329  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:dap");
1330 
1331  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion", (const xmlChar*)"3.2") < 0)
1332  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1333 
1334  if (!get_request_xml_base().empty()) {
1335  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml", (const xmlChar*)c_xml_namespace.c_str()) < 0)
1336  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1337 
1338  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base", (const xmlChar*)get_request_xml_base().c_str()) < 0)
1339  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1340  }
1341 
1342  // Print the global attributes
1343  d_attr.print_xml_writer(xml);
1344 
1345  // Print each variable
1346  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1347 
1348  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "blob") < 0)
1349  throw InternalErr(__FILE__, __LINE__, "Could not write blob element");
1350  string cid = "cid:" + blob;
1351  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "href", (const xmlChar*) cid.c_str()) < 0)
1352  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for d_name");
1353  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1354  throw InternalErr(__FILE__, __LINE__, "Could not end blob element");
1355 
1356  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1357  throw InternalErr(__FILE__, __LINE__, "Could not end Dataset element");
1358 
1359  out << xml.get_doc();// << ends;// << endl;
1360 }
1361 
1375 void
1376 DDS::print_dmr(ostream &out, bool constrained)
1377 {
1378  if (get_dap_major() < 4)
1379  throw InternalErr(__FILE__, __LINE__, "Tried to print a DMR with DAP major version less than 4");
1380 
1381  XMLWriter xml(" ");
1382 
1383  // DAP4 wraps a dataset in a top-level Group element.
1384  if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Group") < 0)
1385  throw InternalErr(__FILE__, __LINE__, "Could not write Group element");
1386 
1387  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xml",
1388  (const xmlChar*) c_xml_namespace.c_str()) < 0)
1389  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xml");
1390 
1391  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns:xsi", (const xmlChar*) c_xml_xsi.c_str())
1392  < 0)
1393  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:xsi");
1394 
1395  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xsi:schemaLocation",
1396  (const xmlChar*) c_dap_40_n_sl.c_str()) < 0)
1397  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns:schemaLocation");
1398 
1399  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xmlns",
1400  (const xmlChar*) get_namespace().c_str()) < 0)
1401  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xmlns");
1402 
1403  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dapVersion",
1404  (const xmlChar*) get_dap_version().c_str()) < 0)
1405  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1406 
1407  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "dmrVersion", (const xmlChar*) get_dmr_version().c_str()) < 0)
1408  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for dapVersion");
1409 
1410  if (!get_request_xml_base().empty()) {
1411  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "xml:base",
1412  (const xmlChar*) get_request_xml_base().c_str()) < 0)
1413  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for xml:base");
1414  }
1415 
1416  if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*) d_name.c_str()) < 0)
1417  throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
1418 
1419  // Print the global attributes
1420  d_attr.print_xml_writer(xml);
1421 
1422  // Print each variable
1423  for_each(var_begin(), var_end(), VariablePrintXMLWriter(xml, constrained));
1424 
1425  if (xmlTextWriterEndElement(xml.get_writer()) < 0)
1426  throw InternalErr(__FILE__, __LINE__, "Could not end the top-level Group element");
1427 
1428  out << xml.get_doc();
1429 }
1430 
1431 // Used by DDS::send() when returning data from a function call.
1446 bool
1448 {
1449  // The dataset must have a d_name
1450  if (d_name == "") {
1451  cerr << "A dataset must have a d_name" << endl;
1452  return false;
1453  }
1454 
1455  string msg;
1456  if (!unique_names(vars, d_name, "Dataset", msg))
1457  return false;
1458 
1459  if (all)
1460  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1461  if (!(*i)->check_semantics(msg, true))
1462  return false;
1463 
1464  return true;
1465 }
1466 
1490 bool
1491 DDS::mark(const string &n, bool state)
1492 {
1493  unique_ptr<BaseType::btp_stack> s(new BaseType::btp_stack);
1494 
1495  DBG2(cerr << "DDS::mark: Looking for " << n << endl);
1496 
1497  BaseType *variable = var(n, s.get());
1498  if (!variable) {
1499  throw Error(malformed_expr, "Could not find variable " + n);
1500  }
1501 
1502  variable->set_send_p(state);
1503 
1504  DBG2(cerr << "DDS::mark: Set variable " << variable->d_name()
1505  << " (a " << variable->type_name() << ")" << endl);
1506 
1507  // Now check the btp_stack and run BaseType::set_send_p for every
1508  // BaseType pointer on the stack. Using BaseType::set_send_p() will
1509  // set the property for a Constructor but not its contained variables
1510  // which preserves the semantics of projecting just one field.
1511  while (!s->empty()) {
1512  s->top()->BaseType::set_send_p(state);
1513 
1514  DBG2(cerr << "DDS::mark: Set variable " << s->top()->d_name()
1515  << " (a " << s->top()->type_name() << ")" << endl);
1516 
1517  string parent_name = (s->top()->get_parent()) ? s->top()->get_parent()->name(): "none";
1518  string parent_type = (s->top()->get_parent()) ? s->top()->get_parent()->type_name(): "none";
1519  DBG2(cerr << "DDS::mark: Parent variable " << parent_name << " (a " << parent_type << ")" << endl);
1520 
1521  s->pop();
1522  }
1523 
1524  return true;
1525 }
1526 
1532 void
1533 DDS::mark_all(bool state)
1534 {
1535  for (Vars_iter i = vars.begin(); i != vars.end(); i++)
1536  (*i)->set_send_p(state);
1537 }
1538 
1546 void
1547 DDS::dump(ostream &strm) const
1548 {
1549  strm << DapIndent::LMarg << "DDS::dump - ("
1550  << (void *)this << ")" << endl ;
1551  DapIndent::Indent() ;
1552  strm << DapIndent::LMarg << "d_name: " << d_name << endl ;
1553  strm << DapIndent::LMarg << "filename: " << d_filename << endl ;
1554  strm << DapIndent::LMarg << "protocol major: " << d_dap_major << endl;
1555  strm << DapIndent::LMarg << "protocol minor: " << d_dap_minor << endl;
1556  strm << DapIndent::LMarg << "factory: " << (void *)d_factory << endl ;
1557 
1558  strm << DapIndent::LMarg << "global attributes:" << endl ;
1559  DapIndent::Indent() ;
1560  d_attr.dump(strm) ;
1561  DapIndent::UnIndent() ;
1562 
1563  if (vars.size()) {
1564  strm << DapIndent::LMarg << "vars:" << endl ;
1565  DapIndent::Indent() ;
1566  Vars_citer i = vars.begin() ;
1567  Vars_citer ie = vars.end() ;
1568  for (; i != ie; i++) {
1569  (*i)->dump(strm) ;
1570  }
1571  DapIndent::UnIndent() ;
1572  }
1573  else {
1574  strm << DapIndent::LMarg << "vars: none" << endl ;
1575  }
1576 
1577  DapIndent::UnIndent() ;
1578 }
1579 
1580 } // namespace libdap
A multidimensional array of identical data types.
Definition: Array.h:113
Contains the attributes for a dataset.
Definition: AttrTable.h:143
virtual AttrTable * append_container(const string &name)
Add a container to the attribute table.
Definition: AttrTable.cc:410
virtual AttrTable * get_attr_table(const string &name)
Get an attribute container.
Definition: AttrTable.cc:607
virtual Attr_iter attr_end()
Definition: AttrTable.cc:719
virtual string get_type(const string &name)
Get the type name of an attribute within this attribute table.
Definition: AttrTable.cc:613
virtual vector< string > * get_attr_vector(const string &name)
Get a vector-valued attribute.
Definition: AttrTable.cc:653
virtual unsigned int append_attr(const string &name, const string &type, const string &value)
Add an attribute to the table.
Definition: AttrTable.cc:307
virtual Attr_iter attr_begin()
Definition: AttrTable.cc:711
virtual string get_name() const
Get the name of this attribute table.
Definition: AttrTable.cc:238
void print_xml_writer(XMLWriter &xml)
Definition: AttrTable.cc:1425
virtual unsigned int get_size() const
Get the number of entries in this attribute table.
Definition: AttrTable.cc:231
virtual void dump(ostream &strm) const
dumps information about this object
Definition: AttrTable.cc:1510
virtual AttrType get_attr_type(const string &name)
Get the type of an attribute.
Definition: AttrTable.cc:621
The basic data type for the DODS DAP types.
Definition: BaseType.h:118
virtual BaseType * ptr_duplicate()=0
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:375
virtual AttrTable & get_attr_table()
Definition: BaseType.cc:578
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:316
virtual bool is_vector_type() const
Returns true if the instance is a vector (i.e., array) type variable.
Definition: BaseType.cc:398
virtual bool is_constructor_type() const
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable.
Definition: BaseType.cc:408
virtual void set_send_p(bool state)
Definition: BaseType.cc:564
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:754
BaseType * var(const string &name, bool exact_match=true, btp_stack *s=nullptr) override
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition: Constructor.cc:185
void add_var(BaseType *bt, Part part=nil) override
Definition: Constructor.cc:323
Vars_iter var_end()
Definition: Constructor.cc:280
void add_var_nocopy(BaseType *bt, Part part=nil) override
Definition: Constructor.cc:345
Vars_iter var_begin()
Definition: Constructor.cc:272
virtual void del_var(const string &name)
Remove an element from a Constructor.
Definition: Constructor.cc:362
Hold attribute data for a DAP2 dataset.
Definition: DAS.h:122
virtual AttrTable * get_top_level_attributes()
Returns the top most set of attributes.
Definition: DAS.h:166
AttrTable * get_table(AttrTable::Attr_iter &i)
Returns the referenced variable attribute table.
Definition: DAS.cc:177
virtual string container_name() const
Returns the name of the current attribute container when multiple files used to build this DAS.
Definition: DAS.h:149
void set_dataset_name(const string &n)
Definition: DDS.cc:292
void set_dap_major(int p)
Definition: DDS.cc:333
void mark_all(bool state)
Definition: DDS.cc:1533
void print_dmr(ostream &out, bool constrained)
Print the DAP4 DMR object using a DDS.
Definition: DDS.cc:1376
void add_var_nocopy(BaseType *bt)
Adds the variable to the DDS.
Definition: DDS.cc:567
bool check_semantics(bool all=false)
Check the semantics of each of the variables represented in the DDS.
Definition: DDS.cc:1447
string filename() const
Definition: DDS.cc:316
virtual AttrTable & get_attr_table()
Definition: DDS.cc:301
uint64_t get_request_size_kb(bool constrained)
Get the estimated response size in kilobytes.
Definition: DDS.cc:522
virtual void transfer_attributes(DAS *das)
Definition: DDS.cc:246
void set_dap_minor(int p)
Definition: DDS.cc:352
string get_namespace() const
Get the namespace associated with the DDS - likely set only by DDX responses.
Definition: DDS.h:279
int num_var()
Returns the number of variables in the DDS.
Definition: DDS.cc:774
void print(FILE *out)
Print the entire DDS to the specified file.
Definition: DDS.cc:924
int get_request_size(bool constrained)
Get the estimated response size in bytes.
Definition: DDS.cc:495
string get_dataset_name() const
Definition: DDS.cc:285
void del_var(const string &n)
Removes a variable from the DDS.
Definition: DDS.cc:589
void parse(string fname)
Parse a DDS from a file with the given d_name.
Definition: DDS.cc:843
BaseType * var(const string &n, BaseType::btp_stack &s)
Definition: DDS.cc:645
void print_xml(FILE *out, bool constrained, const string &blob="")
Definition: DDS.cc:1249
void insert_var(Vars_iter i, BaseType *ptr)
Insert a variable before the referenced element.
Definition: DDS.cc:754
bool mark(const string &name, bool state)
Mark the send_p flag of the named variable to state.
Definition: DDS.cc:1491
DDS(BaseTypeFactory *factory, const string &name="")
Definition: DDS.cc:168
void tag_nested_sequences()
Traverse DDS, set Sequence leaf nodes.
Definition: DDS.cc:831
DAS * get_das()
Get a DAS object.
Definition: DDS.cc:1082
Vars_iter var_begin()
Definition: DDS.h:344
void print_constrained(FILE *out)
Print a constrained DDS to the specified file.
Definition: DDS.cc:1203
string container_name()
Definition: DDS.cc:440
void insert_var_nocopy(Vars_iter i, BaseType *ptr)
Definition: DDS.cc:767
string get_request_xml_base() const
Get the URL that will return this DDS/DDX/DataThing.
Definition: DDS.h:273
Vars_iter var_end()
Return an iterator.
Definition: DDS.h:349
int get_dap_major() const
Get the DAP major version as sent by the client.
Definition: DDS.h:257
void set_dap_version(const string &version_string="2.0")
Definition: DDS.cc:369
Structure * container()
Definition: DDS.cc:476
void add_var(BaseType *bt)
Adds a copy of the variable to the DDS. Using the ptr_duplicate() method, perform a deep copy on the ...
Definition: DDS.cc:543
void print_xml_writer(ostream &out, bool constrained, const string &blob="")
Definition: DDS.cc:1304
void print_das(ostream &out)
write the DAS response given the attribute information in the DDS
Definition: DDS.cc:1065
virtual void dump(ostream &strm) const
dumps information about this object
Definition: DDS.cc:1547
libdap base object for common functionality of libdap objects
Definition: DapObj.h:51
A class for error processing.
Definition: Error.h:94
Holds the Grid data type.
Definition: Grid.h:123
Array * get_array()
Returns the Grid Array. This method returns the array using an Array*, so no cast is required.
Definition: Grid.cc:489
A class for software fault reporting.
Definition: InternalErr.h:65
Holds a sequence.
Definition: Sequence.h:163
virtual void set_leaf_sequence(int lvl=1)
Mark the Sequence which holds the leaf elements.
Definition: Sequence.cc:1233
Holds a structure (aggregate) type.
Definition: Structure.h:84
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:309
top level DAP object to house generic methods
Definition: AlarmHandler.h:36
bool has_dap2_attributes(AttrTable &a)
Definition: DDS.cc:954
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
string add_space_encoding(const string &s)
Definition: AttrTable.cc:78
string AttrType_to_String(const AttrType at)
Definition: AttrTable.cc:97
AttrType
Definition: AttrTable.h:81
void fillConstructorAttrTable(AttrTable *at, BaseType *bt)
Recursive helper function for Building DAS entries for Constructor types.
Definition: DDS.cc:1126
string id2www(string in, const string &allowable)
Definition: escaping.cc:153
Pass parameters by reference to a parser.
Definition: parser.h:69