libdap++  Updated for version 3.12.0
Structure.cc
Go to the documentation of this file.
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 "XDRStreamMarshaller.h"
60 #include "util.h"
61 #include "debug.h"
62 #include "InternalErr.h"
63 #include "escaping.h"
64 
65 using std::cerr;
66 using std::endl;
67 
68 namespace libdap {
69 
70 #if 0
71 
75 void
76 Structure::m_duplicate(const Structure &s)
77 {
79 #if 0
80  Structure &cs = const_cast<Structure &>(s);
81 
82  DBG(cerr << "Copying structure: " << name() << endl);
83 
84  for (Vars_iter i = cs.d_vars.begin(); i != cs.d_vars.end(); i++) {
85  DBG(cerr << "Copying field: " << (*i)->name() << endl);
86  // Jose Garcia
87  // I think this assert here is part of a debugging
88  // process since it is going along with a DBG call
89  // I leave it here since it can be remove by defining NDEBUG.
90  // assert(*i);
91  BaseType *btp = (*i)->ptr_duplicate();
92  btp->set_parent(this);
93  d_vars.push_back(btp);
94  }
95 #endif
96 }
97 #endif
98 
107 {}
108 
118 Structure::Structure(const string &n, const string &d)
120 {}
121 
124 {
125  m_duplicate(rhs);
126 }
127 
129 {
130  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
131  BaseType *btp = *i ;
132  delete btp ; btp = 0;
133  }
134 }
135 
136 BaseType *
138 {
139  return new Structure(*this);
140 }
141 
142 Structure &
144 {
145  if (this == &rhs)
146  return *this;
147 
148  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
149 
150  m_duplicate(rhs);
151 
152  return *this;
153 }
154 
155 #if 0
156 int
157 Structure::element_count(bool leaves)
158 {
159  if (!leaves)
160  return d_vars.size();
161  else {
162  int i = 0;
163  for (Vars_iter j = d_vars.begin(); j != d_vars.end(); j++) {
164  i += (*j)->element_count(leaves);
165  }
166  return i;
167  }
168 }
169 #endif
170 
171 bool
173 {
174  bool linear = true;
175  for (Vars_iter i = d_vars.begin(); linear && i != d_vars.end(); i++) {
176  if ((*i)->type() == dods_structure_c)
177  linear = linear && static_cast<Structure*>((*i))->is_linear();
178  else
179  linear = linear && (*i)->is_simple_type();
180  }
181 
182  return linear;
183 }
184 
185 #if 0
186 void
187 Structure::set_send_p(bool state)
188 {
189  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
190  (*i)->set_send_p(state);
191  }
192 
193  BaseType::set_send_p(state);
194 }
195 
196 void
197 Structure::set_read_p(bool state)
198 {
199  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
200  (*i)->set_read_p(state);
201  }
202 
203  BaseType::set_read_p(state);
204 }
205 #endif
206 #if 0
207 
212 void
213 Structure::set_in_selection(bool state)
214 {
215  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
216  (*i)->set_in_selection(state);
217  }
218 
220 }
221 #endif
222 
223 void
225 {
226  for (Vars_iter i = var_begin(); i != var_end(); i++) {
227  if ((*i)->type() == dods_sequence_c)
228  static_cast<Sequence&>(**i).set_leaf_sequence(++level);
229  else if ((*i)->type() == dods_structure_c)
230  static_cast<Structure&>(**i).set_leaf_sequence(level);
231  }
232 }
233 
234 #if 0
235 
239 void
241 {
242  // Jose Garcia
243  // Passing and invalid pointer to an object is a developer's error.
244  if (!bt)
245  throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
246 
247  if (bt->is_dap4_only_type())
248  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
249 
250  // Jose Garcia
251  // Now we add a copy of bt so the external user is able to destroy bt as
252  // he/she wishes. The policy is: "If it is allocated outside, it is
253  // deallocated outside, if it is allocated inside, it is deallocated
254  // inside"
255  BaseType *btp = bt->ptr_duplicate();
256  btp->set_parent(this);
257  d_vars.push_back(btp);
258 }
259 
264 void
265 Structure::add_var_nocopy(BaseType *bt, Part)
266 {
267  if (!bt)
268  throw InternalErr(__FILE__, __LINE__, "The BaseType parameter cannot be null.");
269 
270  if (bt->is_dap4_only_type())
271  throw InternalErr(__FILE__, __LINE__, "Attempt to add a DAP4 type to a DAP2 Structure.");
272 
273  bt->set_parent(this);
274  d_vars.push_back(bt);
275 }
276 
277 
281 void
282 Structure::del_var(const string &n)
283 {
284  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
285  if ((*i)->name() == n) {
286  BaseType *bt = *i ;
287  d_vars.erase(i) ;
288  delete bt ; bt = 0;
289  return;
290  }
291  }
292 }
293 #endif
294 #if 0
295 
300 bool Structure::read()
301 {
302  if (!read_p()) {
303  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
304  (*i)->read();
305  }
306  set_read_p(true);
307  }
308 
309  return false;
310 }
311 #endif
312 #if 0
313 // TODO Recode to use width(bool)
314 unsigned int
316 {
317  unsigned int sz = 0;
318 
319  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
320  sz += (*i)->width();
321  }
322 
323  return sz;
324 }
325 
333 unsigned int
334 Structure::width(bool constrained)
335 {
336  unsigned int sz = 0;
337 
338  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
339  if (constrained) {
340  if ((*i)->send_p())
341  sz += (*i)->width(constrained);
342  }
343  else {
344  sz += (*i)->width(constrained);
345  }
346  }
347 
348  return sz;
349 }
350 #endif
351 
352 #if 0
353 void
354 Structure::intern_data(ConstraintEvaluator & eval, DDS & dds)
355 {
356  DBG(cerr << "Structure::intern_data: " << name() << endl);
357  if (!read_p())
358  read(); // read() throws Error and InternalErr
359 
360  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
361  if ((*i)->send_p()) {
362  (*i)->intern_data(eval, dds);
363  }
364  }
365 }
366 
367 bool
368 Structure::serialize(ConstraintEvaluator &eval, DDS &dds,
369  Marshaller &m, bool ce_eval)
370 {
371  dds.timeout_on();
372 
373  if (!read_p())
374  read(); // read() throws Error and InternalErr
375 
376 #if EVAL
377  if (ce_eval && !eval.eval_selection(dds, dataset()))
378  return true;
379 #endif
380 
381  dds.timeout_off();
382 
383  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
384  if ((*i)->send_p()) {
385 #ifdef CHECKSUMS
386  XDRStreamMarshaller *sm = dynamic_cast<XDRStreamMarshaller*>(&m);
387  if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
388  sm->reset_checksum();
389 
390  (*i)->serialize(eval, dds, m, false);
391 
392  if (sm && sm->checksums() && (*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
393  sm->get_checksum();
394 #else
395  (*i)->serialize(eval, dds, m, false);
396 #endif
397  }
398  }
399 
400  return true;
401 }
402 
403 bool
404 Structure::deserialize(UnMarshaller &um, DDS *dds, bool reuse)
405 {
406  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
407  (*i)->deserialize(um, dds, reuse);
408  }
409 
410  return false;
411 }
412 #endif
413 #if 0
414 
423 unsigned int
424 Structure::val2buf(void *, bool)
425 {
426  return sizeof(Structure);
427 }
428 
432 unsigned int
433 Structure::buf2val(void **)
434 {
435  return sizeof(Structure);
436 }
437 #endif
438 
439 #if 0
440 BaseType *
441 Structure::var(const string &name, bool exact_match, btp_stack *s)
442 {
443  string n = www2id(name);
444 
445  if (exact_match)
446  return m_exact_match(n, s);
447  else
448  return m_leaf_match(n, s);
449 }
450 
452 BaseType *
453 Structure::var(const string &n, btp_stack &s)
454 {
455  string name = www2id(n);
456 
457  BaseType *btp = m_exact_match(name, &s);
458  if (btp)
459  return btp;
460 
461  return m_leaf_match(name, &s);
462 }
463 #endif
464 #if 0
465 // Private method to find a variable using the shorthand name. This
466 // should be moved to Constructor.
467 BaseType *
468 Structure::m_leaf_match(const string &name, btp_stack *s)
469 {
470  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
471  if ((*i)->name() == name) {
472  if (s) {
473  DBG(cerr << "Pushing " << this->name() << endl);
474  s->push(static_cast<BaseType *>(this));
475  }
476  return *i;
477  }
478  if ((*i)->is_constructor_type()) {
479  BaseType *btp = (*i)->var(name, false, s);
480  if (btp) {
481  if (s) {
482  DBG(cerr << "Pushing " << this->name() << endl);
483  s->push(static_cast<BaseType *>(this));
484  }
485  return btp;
486  }
487  }
488  }
489 
490  return 0;
491 }
492 
493 // Breadth-first search for NAME. If NAME contains one or more dots (.)
494 // TODO The btp_stack is not needed since there are 'back pointers' in
495 // BaseType.
496 BaseType *
497 Structure::m_exact_match(const string &name, btp_stack *s)
498 {
499  // Look for name at the top level first.
500  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
501  if ((*i)->name() == name) {
502  if (s)
503  s->push(static_cast<BaseType *>(this));
504 
505  return *i;
506  }
507  }
508 
509  // If it was not found using the simple search, look for a dot and
510  // search the hierarchy.
511  string::size_type dot_pos = name.find("."); // zero-based index of `.'
512  if (dot_pos != string::npos) {
513  string aggregate = name.substr(0, dot_pos);
514  string field = name.substr(dot_pos + 1);
515 
516  BaseType *agg_ptr = var(aggregate);
517  if (agg_ptr) {
518  if (s)
519  s->push(static_cast<BaseType *>(this));
520 
521  return agg_ptr->var(field, true, s); // recurse
522  }
523  else
524  return 0; // qualified names must be *fully* qualified
525  }
526 
527  return 0;
528 }
529 #endif
530 // TODO Can these be removed and the versions in Constructor used instead?
531 // Yes.
532 #if 0
533 void
534 Structure::print_val(FILE *out, string space, bool print_decl_p)
535 {
536  ostringstream oss;
537  print_val(oss, space, print_decl_p);
538  fwrite(oss.str().data(), sizeof(char), oss.str().length(), out);
539 }
540 
541 void
542 Structure::print_val(ostream &out, string space, bool print_decl_p)
543 {
544  if (print_decl_p) {
545  print_decl(out, space, false);
546  out << " = " ;
547  }
548 
549  out << "{ " ;
550  for (Vars_citer i = d_vars.begin(); i != d_vars.end();
551  i++, (void)(i != d_vars.end() && out << ", ")) {
552  (*i)->print_val(out, "", false);
553  }
554 
555  out << " }" ;
556 
557  if (print_decl_p)
558  out << ";\n" ;
559 }
560 #endif
561 
562 #if 0
563 bool
564 Structure::check_semantics(string &msg, bool all)
565 {
566  if (!BaseType::check_semantics(msg))
567  return false;
568 
569  bool status = true;
570 
571  if (!unique_names(d_vars, name(), type_name(), msg))
572  return false;
573 
574  if (all) {
575  for (Vars_iter i = d_vars.begin(); i != d_vars.end(); i++) {
576  //assert(*i);
577  if (!(*i)->check_semantics(msg, true)) {
578  status = false;
579  goto exit;
580  }
581  }
582  }
583 
584 exit:
585  return status;
586 }
587 #endif
588 
597 void
598 Structure::dump(ostream &strm) const
599 {
600  strm << DapIndent::LMarg << "Structure::dump - ("
601  << (void *)this << ")" << endl ;
603  Constructor::dump(strm) ;
605 }
606 
607 } // namespace libdap
608