libdap Updated for version 3.18.1
Structure.cc
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of libdap, A C++ implementation of the OPeNDAP Data
5// Access Protocol.
6
7// Copyright (c) 2002,2003 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26// (c) COPYRIGHT URI/MIT 1994-1999
27// Please read the full copyright statement in the file COPYRIGHT_URI.
28//
29// Authors:
30// jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
31
32// Implementation for the class Structure
33//
34// jhrg 9/14/94
35
36//#define DODS_DEBUG
37
38#include "config.h"
39
40#include <sstream>
41
42#include "Byte.h"
43#include "Int16.h"
44#include "UInt16.h"
45#include "Int32.h"
46#include "UInt32.h"
47#include "Float32.h"
48#include "Float64.h"
49#include "Str.h"
50#include "Url.h"
51#include "Array.h"
52#include "Structure.h"
53#include "Sequence.h"
54#include "Grid.h"
55
56#include "DDS.h"
57#include "ConstraintEvaluator.h"
58
59#include "D4Attributes.h"
60#include "D4Group.h"
61
62#include "XDRStreamMarshaller.h"
63#include "util.h"
64#include "debug.h"
65#include "InternalErr.h"
66#include "escaping.h"
67
68using std::cerr;
69using std::endl;
70
71namespace libdap {
72
73#if 0
78void
79Structure::m_duplicate(const Structure &s)
80{
81 Constructor::m_duplicate(s);
82#if 0
83 Structure &cs = const_cast<Structure &>(s);
84
85 DBG(cerr << "Copying structure: " << name() << endl);
86
87 for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) {
88 DBG(cerr << "Copying field: " << (*i)->name() << endl);
89 // Jose Garcia
90 // I think this assert here is part of a debugging
91 // process since it is going along with a DBG call
92 // I leave it here since it can be remove by defining NDEBUG.
93 // assert(*i);
94 BaseType *btp = (*i)->ptr_duplicate();
95 btp->set_parent(this);
96 d_vars.push_back(btp);
97 }
98#endif
99}
100#endif
101
109Structure::Structure(const string &n) : Constructor(n, dods_structure_c)
110{}
111
121Structure::Structure(const string &n, const string &d)
122 : Constructor(n, d, dods_structure_c)
123{}
124
127{
128 DBG(cerr << "In Structure::copy_ctor for " << name() << endl);
129 //m_duplicate(rhs);
130}
131
132Structure::~Structure()
133{
134}
135
136BaseType *
138{
139 return new Structure(*this);
140}
141
151BaseType *
153{
154 // For this class, ptr_duplicate() calls the const ctor which calls
155 // Constructor's const ctor which calls Constructor::m_duplicate().
156 // Here we replicate some of that functionality, but instead call
157 // transform_to_dap4() on the contained variables.
158
159 // Structure *dest = static_cast<Structure*>(ptr_duplicate());
160 Structure *dest = new Structure(name());
161
163 dest->set_parent(container);
164
165 return dest;
166}
167
168Structure &
169Structure::operator=(const Structure &rhs)
170{
171 DBG(cerr << "Entering Structure::operator=" << endl);
172 if (this == &rhs)
173 return *this;
174
175 dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
176
177 //m_duplicate(rhs);
178
179 DBG(cerr << "Exiting Structure::operator=" << endl);
180 return *this;
181}
182
183#if 0
184int
185Structure::element_count(bool leaves)
186{
187 if (!leaves)
188 return d_vars.size();
189 else {
190 int i = 0;
191 for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
192 i += (*j)->element_count(leaves);
193 }
194 return i;
195 }
196}
197#endif
198
199bool
201{
202 bool linear = true;
203 for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) {
204 if ((*i)->type() == dods_structure_c)
205 linear = linear && static_cast<Structure*>((*i))->is_linear();
206 else
207 linear = linear && (*i)->is_simple_type();
208 }
209
210 return linear;
211}
212
213#if 0
214void
215Structure::set_send_p(bool state)
216{
217 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
218 (*i)->set_send_p(state);
219 }
220
222}
223
224void
225Structure::set_read_p(bool state)
226{
227 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
228 (*i)->set_read_p(state);
229 }
230
232}
233#endif
234#if 0
240void
242{
243 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
244 (*i)->set_in_selection(state);
245 }
246
248}
249#endif
251void
253{
254 for (Vars_iter i = var_begin(); i != var_end(); i++) {
255 if ((*i)->type() == dods_sequence_c)
256 static_cast<Sequence&>(**i).set_leaf_sequence(++level);
257 else if ((*i)->type() == dods_structure_c)
258 static_cast<Structure&>(**i).set_leaf_sequence(level);
259 }
260}
261
262#if 0
267void
269{
270 // Jose Garcia
271 // Passing and invalid pointer to an object is a developer's error.
272 if (!bt)
273 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
274
275 if (bt->is_dap4_only_type())
276 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
277
278 // Jose Garcia
279 // Now we add a copy of bt so the external user is able to destroy bt as
280 // he/she wishes. The policy is: "If it is allocated outside, it is
281 // deallocated outside, if it is allocated inside, it is deallocated
282 // inside"
283 BaseType *btp = bt->ptr_duplicate();
284 btp->set_parent(this);
285 d_vars.push_back(btp);
286}
287
292void
293Structure::add_var_nocopy(BaseType *bt, Part)
294{
295 if (!bt)
296 throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
297
298 if (bt->is_dap4_only_type())
299 throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
300
301 bt->set_parent(this);
302 d_vars.push_back(bt);
303}
304
305
309void
310Structure::del_var(const string &n)
311{
312 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
313 if ((*i)->name() == n) {
314 BaseType *bt = *i ;
315 d_vars.erase(i) ;
316 delete bt ; bt = 0;
317 return;
318 }
319 }
320}
321#endif
322#if 0
328bool Structure::read()
329{
330 if (!read_p()) {
331 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
332 (*i)->read();
333 }
334 set_read_p(true);
335 }
336
337 return false;
338}
339#endif
340#if 0
341// TODO Recode to use width(bool)
342unsigned int
344{
345 unsigned int sz = 0;
346
347 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
348 sz += (*i)->width();
349 }
350
351 return sz;
352}
353
361unsigned int
362Structure::width(bool constrained)
363{
364 unsigned int sz = 0;
365
366 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
367 if (constrained) {
368 if ((*i)->send_p())
369 sz += (*i)->width(constrained);
370 }
371 else {
372 sz += (*i)->width(constrained);
373 }
374 }
375
376 return sz;
377}
378#endif
379
380#if 0
381void
382Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
383{
384 DBG(cerr << "Structure::intern_data: " << name() << endl);
385 if (!read_p())
386 read(); // read() throws Error and InternalErr
387
388 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
389 if ((*i)->send_p()) {
390 (*i)->intern_data(eval, dds);
391 }
392 }
393}
394
395bool
396Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
397 Marshaller &m, bool ce_eval)
398{
399#if USE_LOCAL_TIMEOUT_SCHEME
400 dds.timeout_on();
401#endif
402 if (!read_p())
403 read(); // read() throws Error and InternalErr
404
405#if EVAL
406 if (ce_eval && !eval.eval_selection(dds, dataset()))
407 return true;
408#endif
409#if USE_LOCAL_TIMEOUT_SCHEME
410 dds.timeout_off();
411#endif
412 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
413 if ((*i)->send_p()) {
414#ifdef CHECKSUMS
415 XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
416 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
417 sm->reset_checksum();
418
419 (*i)->serialize(eval, dds, m, false);
420
421 if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
422 sm->get_checksum();
423#else
424 (*i)->serialize(eval, dds, m, false);
425#endif
426 }
427 }
428
429 return true;
430}
431
432bool
433Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
434{
435 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
436 (*i)->deserialize(um, dds, reuse);
437 }
438
439 return false;
440}
441#endif
442#if 0
452unsigned int
453Structure::val2buf(void *, bool)
454{
455 return sizeof(Structure);
456}
457
461unsigned int
462Structure::buf2val(void **)
463{
464 return sizeof(Structure);
465}
466#endif
467
468#if 0
469BaseType *
470Structure::var(const string &name, bool exact_match, btp_stack *s)
471{
472 string n = www2id(name);
473
474 if (exact_match)
475 return m_exact_match(n, s);
476 else
477 return m_leaf_match(n, s);
478}
479
481BaseType *
482Structure::var(const string &n, btp_stack &s)
483{
484 string name = www2id(n);
485
486 BaseType *btp = m_exact_match(name, &s);
487 if (btp)
488 return btp;
489
490 return m_leaf_match(name, &s);
491}
492#endif
493#if 0
494// Private method to find a variable using the shorthand name. This
495// should be moved to Constructor.
496BaseType *
497Structure::m_leaf_match(const string &name, btp_stack *s)
498{
499 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
500 if ((*i)->name() == name) {
501 if (s) {
502 DBG(cerr << "Pushing " << this->name() << endl);
503 s->push(static_cast<BaseType *>(this));
504 }
505 return *i;
506 }
507 if ((*i)->is_constructor_type()) {
508 BaseType *btp = (*i)->var(name, false, s);
509 if (btp) {
510 if (s) {
511 DBG(cerr << "Pushing " << this->name() << endl);
512 s->push(static_cast<BaseType *>(this));
513 }
514 return btp;
515 }
516 }
517 }
518
519 return 0;
520}
521
522// Breadth-first search for NAME. If NAME contains one or more dots (.)
523// TODO The btp_stack is not needed since there are 'back pointers' in
524// BaseType.
525BaseType *
526Structure::m_exact_match(const string &name, btp_stack *s)
527{
528 // Look for name at the top level first.
529 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
530 if ((*i)->name() == name) {
531 if (s)
532 s->push(static_cast<BaseType *>(this));
533
534 return *i;
535 }
536 }
537
538 // If it was not found using the simple search, look for a dot and
539 // search the hierarchy.
540 string::size_type dot_pos = name.find("."); // zero-based index of `.'
541 if (dot_pos != string::npos) {
542 string aggregate = name.substr(0, dot_pos);
543 string field = name.substr(dot_pos + 1);
544
545 BaseType *agg_ptr = var(aggregate);
546 if (agg_ptr) {
547 if (s)
548 s->push(static_cast<BaseType *>(this));
549
550 return agg_ptr->var(field, true, s); // recurse
551 }
552 else
553 return 0; // qualified names must be *fully* qualified
554 }
555
556 return 0;
557}
558#endif
559#if 0
560void
561Structure::print_val(FILE *out, string space, bool print_decl_p)
562{
563 ostringstream oss;
564 print_val(oss, space, print_decl_p);
565 fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
566}
567
568void
569Structure::print_val(ostream &out, string space, bool print_decl_p)
570{
571 if (print_decl_p) {
572 print_decl(out, space, false);
573 out << " = " ;
574 }
575
576 out << "{ " ;
577 for (Vars_citer i = d_vars.begin(); i != d_vars.end();
578 i++, (void)(i != d_vars.end() && out << ", ")) {
579 (*i)->print_val(out, "", false);
580 }
581
582 out << " }" ;
583
584 if (print_decl_p)
585 out << ";\n" ;
586}
587#endif
588
589#if 0
590bool
591Structure::check_semantics(string &msg, bool all)
592{
594 return false;
595
596 bool status = true;
597
598 if (!unique_names(d_vars, name(), type_name(), msg))
599 return false;
600
601 if (all) {
602 for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
603 //assert(*i);
604 if (!(*i)->check_semantics(msg, true)) {
605 status = false;
606 goto exit;
607 }
608 }
609 }
610
611exit:
612 return status;
613}
614#endif
615
624void
625Structure::dump(ostream &strm) const
626{
627 strm << DapIndent::LMarg << "Structure::dump - ("
628 << (void *)this << ")" << endl ;
629 DapIndent::Indent() ;
630 Constructor::dump(strm) ;
631 DapIndent::UnIndent() ;
632}
633
634} // namespace libdap
635
The basic data type for the DODS DAP types.
Definition: BaseType.h:118
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:324
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual void set_in_selection(bool state)
Definition: BaseType.cc:639
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:425
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:461
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:303
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:654
virtual void set_send_p(bool state)
Definition: BaseType.cc:513
virtual BaseType * ptr_duplicate()=0
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1130
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:125
virtual unsigned int width(bool constrained=false) const
Definition: Constructor.cc:224
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: Constructor.cc:169
virtual void add_var(BaseType *bt, Part part=nil)
Definition: Constructor.cc:382
virtual BaseType * var(const string &name, bool exact_match=true, btp_stack *s=0)
btp_stack no longer needed; use back pointers (BaseType::get_parent())
Definition: Constructor.cc:242
BaseType * transform_to_dap4(D4Group *root, Constructor *dest)
DAP2 to DAP4 transform.
Definition: Constructor.cc:137
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Constructor.cc:515
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Move data to the net, then remove them from the object.
Definition: Constructor.cc:479
virtual void intern_data()
Read data into this variable.
Definition: Constructor.cc:531
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Constructor.cc:827
Vars_iter var_end()
Definition: Constructor.cc:339
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Constructor.cc:625
virtual void set_send_p(bool state)
Definition: Constructor.cc:183
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: Constructor.cc:601
virtual void add_var_nocopy(BaseType *bt, Part part=nil)
Definition: Constructor.cc:407
virtual void set_in_selection(bool state)
Set the in_selection property.
Definition: Constructor.cc:809
virtual unsigned int buf2val(void **)
Definition: Constructor.h:118
virtual unsigned int val2buf(void *, bool)
Definition: Constructor.h:115
virtual bool read()
simple implementation of read that iterates through vars and calls read on them
Definition: Constructor.cc:451
Vars_iter var_begin()
Definition: Constructor.cc:331
virtual void del_var(const string &name)
Definition: Constructor.cc:423
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: Constructor.cc:193
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: Constructor.cc:767
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:1231
Holds a structure (aggregate) type.
Definition: Structure.h:84
Structure(const string &n)
Definition: Structure.cc:109
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Structure.cc:625
virtual void set_leaf_sequence(int level=1)
Traverse Structure, set Sequence leaf nodes.
Definition: Structure.cc:252
virtual BaseType * transform_to_dap4(D4Group *root, Constructor *container)
Definition: Structure.cc:152
virtual bool is_linear()
Check to see whether this variable can be printed simply.
Definition: Structure.cc:200
virtual BaseType * ptr_duplicate()
Definition: Structure.cc:137
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
Part
Names the parts of multi-section constructor data types.
Definition: Type.h:48