libdap++  Updated for version 3.11.7
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "Byte.h"
41 #include "Int16.h"
42 #include "UInt16.h"
43 #include "Int32.h"
44 #include "UInt32.h"
45 #include "Float32.h"
46 #include "Float64.h"
47 #include "Str.h"
48 #include "Url.h"
49 #include "Array.h"
50 #include "Structure.h"
51 #include "Sequence.h"
52 #include "Grid.h"
53 
54 #include "XDRStreamMarshaller.h"
55 #include "util.h"
56 #include "debug.h"
57 #include "InternalErr.h"
58 #include "escaping.h"
59 
60 using std::cerr;
61 using std::endl;
62 
63 namespace libdap {
64 
65 void
67 {
68  Structure &cs = const_cast<Structure &>(s);
69 
70  DBG(cerr << "Copying structure: " << name() << endl);
71 
72  for (Vars_iter i = cs._vars.begin(); i != cs._vars.end(); i++) {
73  DBG(cerr << "Copying field: " << (*i)->name() << endl);
74  // Jose Garcia
75  // I think this assert here is part of a debugging
76  // process since it is going along with a DBG call
77  // I leave it here since it can be remove by defining NDEBUG.
78  // assert(*i);
79  BaseType *btp = (*i)->ptr_duplicate();
80  btp->set_parent(this);
81  _vars.push_back(btp);
82  }
83 }
84 
93 {}
94 
104 Structure::Structure(const string &n, const string &d)
106 {}
107 
110 {
111  _duplicate(rhs);
112 }
113 
115 {
116  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
117  BaseType *btp = *i ;
118  delete btp ; btp = 0;
119  }
120 }
121 
122 BaseType *
124 {
125  return new Structure(*this);
126 }
127 
128 Structure &
130 {
131  if (this == &rhs)
132  return *this;
133 
134  dynamic_cast<Constructor &>(*this) = rhs; // run Constructor=
135 
136  _duplicate(rhs);
137 
138  return *this;
139 }
140 
141 int
143 {
144  if (!leaves)
145  return _vars.size();
146  else {
147  int i = 0;
148  for (Vars_iter j = _vars.begin(); j != _vars.end(); j++) {
149  j += (*j)->element_count(leaves);
150  }
151  return i;
152  }
153 }
154 
155 bool
157 {
158  bool linear = true;
159  for (Vars_iter i = _vars.begin(); linear && i != _vars.end(); i++) {
160  if ((*i)->type() == dods_structure_c)
161  linear = linear && dynamic_cast<Structure*>((*i))->is_linear();
162  else
163  linear = linear && (*i)->is_simple_type();
164  }
165 
166  return linear;
167 }
168 
169 void
171 {
172  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
173  (*i)->set_send_p(state);
174  }
175 
176  BaseType::set_send_p(state);
177 }
178 
179 void
181 {
182  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
183  (*i)->set_read_p(state);
184  }
185 
186  BaseType::set_read_p(state);
187 }
188 
194 void
196 {
197  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
198  (*i)->set_in_selection(state);
199  }
200 
202 }
203 
205 void
207 {
208  for (Vars_iter i = var_begin(); i != var_end(); i++) {
209  if ((*i)->type() == dods_sequence_c)
210  dynamic_cast<Sequence&>(**i).set_leaf_sequence(++level);
211  else if ((*i)->type() == dods_structure_c)
212  dynamic_cast<Structure&>(**i).set_leaf_sequence(level);
213  }
214 }
215 
220 void
222 {
223  // Jose Garcia
224  // Passing and invalid pointer to an object is a developer's error.
225  if (!bt)
226  throw InternalErr(__FILE__, __LINE__,
227  "The BaseType parameter cannot be null.");
228 
229  // Jose Garcia
230  // Now we add a copy of bt so the external user is able to destroy bt as
231  // he/she wishes. The policy is: "If it is allocated outside, it is
232  // deallocated outside, if it is allocated inside, it is deallocated
233  // inside"
234  BaseType *btp = bt->ptr_duplicate();
235  btp->set_parent(this);
236  _vars.push_back(btp);
237 }
238 
243 void
245 {
246  // Jose Garcia
247  // Passing and invalid pointer to an object is a developer's error.
248  if (!bt)
249  throw InternalErr(__FILE__, __LINE__,
250  "The BaseType parameter cannot be null.");
251 
252  bt->set_parent(this);
253  _vars.push_back(bt);
254 }
255 
256 
260 void
261 Structure::del_var(const string &n)
262 {
263  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
264  if ((*i)->name() == n) {
265  BaseType *bt = *i ;
266  _vars.erase(i) ;
267  delete bt ; bt = 0;
268  return;
269  }
270  }
271 }
272 
278 bool
280 {
281  if( !read_p() )
282  {
283  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
284  (*i)->read() ;
285  }
286  set_read_p(true) ;
287  }
288 
289  return false ;
290 }
291 
292 // TODO Recode to use width(bool)
293 unsigned int
295 {
296  unsigned int sz = 0;
297 
298  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
299  sz += (*i)->width();
300  }
301 
302  return sz;
303 }
304 
312 unsigned int
313 Structure::width(bool constrained)
314 {
315  unsigned int sz = 0;
316 
317  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
318  if (constrained) {
319  if ((*i)->send_p())
320  sz += (*i)->width(constrained);
321  }
322  else {
323  sz += (*i)->width(constrained);
324  }
325  }
326 
327  return sz;
328 }
329 
330 
331 void
333 {
334  DBG(cerr << "Structure::intern_data: " << name() << endl);
335  if (!read_p())
336  read(); // read() throws Error and InternalErr
337 
338  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
339  if ((*i)->send_p()) {
340  (*i)->intern_data(eval, dds);
341  }
342  }
343 }
344 
345 bool
347  Marshaller &m, bool ce_eval)
348 {
349  dds.timeout_on();
350 
351  if (!read_p())
352  read(); // read() throws Error and InternalErr
353 
354 #if EVAL
355  if (ce_eval && !eval.eval_selection(dds, dataset()))
356  return true;
357 #endif
358 
359  dds.timeout_off();
360 
361  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
362  if ((*i)->send_p()) {
363 #ifdef CHECKSUMS
364  XDRStreamMarshaller &sm = dynamic_cast<XDRStreamMarshaller &>(m);
365  if ((*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
366  sm.reset_checksum();
367 
368  (*i)->serialize(eval, dds, sm, false);
369 
370  if ((*i)->type() != dods_structure_c && (*i)->type() != dods_grid_c)
371  cerr << (*i)->name() << ": " << sm.get_checksum() << endl;
372 #else
373  (*i)->serialize(eval, dds, m, false);
374 #endif
375  }
376  }
377 
378  return true;
379 }
380 
381 bool
383 {
384  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
385  (*i)->deserialize(um, dds, reuse);
386  }
387 
388  return false;
389 }
390 
400 unsigned int
401 Structure::val2buf(void *, bool)
402 {
403  return sizeof(Structure);
404 }
405 
409 unsigned int
411 {
412  return sizeof(Structure);
413 }
414 
415 BaseType *
416 Structure::var(const string &name, bool exact_match, btp_stack *s)
417 {
418  string n = www2id(name);
419 
420  if (exact_match)
421  return m_exact_match(n, s);
422  else
423  return m_leaf_match(n, s);
424 }
425 
427 BaseType *
428 Structure::var(const string &n, btp_stack &s)
429 {
430  string name = www2id(n);
431 
432  BaseType *btp = m_exact_match(name, &s);
433  if (btp)
434  return btp;
435 
436  return m_leaf_match(name, &s);
437 }
438 
439 // Private method to find a variable using the shorthand name. This
440 // should be moved to Constructor.
441 BaseType *
442 Structure::m_leaf_match(const string &name, btp_stack *s)
443 {
444  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
445  if ((*i)->name() == name) {
446  if (s) {
447  DBG(cerr << "Pushing " << this->name() << endl);
448  s->push(static_cast<BaseType *>(this));
449  }
450  return *i;
451  }
452  if ((*i)->is_constructor_type()) {
453  BaseType *btp = (*i)->var(name, false, s);
454  if (btp) {
455  if (s) {
456  DBG(cerr << "Pushing " << this->name() << endl);
457  s->push(static_cast<BaseType *>(this));
458  }
459  return btp;
460  }
461  }
462  }
463 
464  return 0;
465 }
466 
467 // Breadth-first search for NAME. If NAME contains one or more dots (.)
468 BaseType *
469 Structure::m_exact_match(const string &name, btp_stack *s)
470 {
471  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
472  DBG(cerr << "Looking at " << (*i)->name() << " in: " << *i
473  << endl);
474  if ((*i)->name() == name) {
475  DBG(cerr << "Found " << (*i)->name() << " in: "
476  << *i << endl);
477  if (s) {
478  DBG(cerr << "Pushing " << this->name() << endl);
479  s->push(static_cast<BaseType *>(this));
480  }
481  return *i;
482  }
483  }
484 
485  string::size_type dot_pos = name.find("."); // zero-based index of `.'
486  if (dot_pos != string::npos) {
487  string aggregate = name.substr(0, dot_pos);
488  string field = name.substr(dot_pos + 1);
489 
490  BaseType *agg_ptr = var(aggregate);
491  if (agg_ptr) {
492  DBG(cerr << "Descending into " << agg_ptr->name() << endl);
493  if (s) {
494  DBG(cerr << "Pushing " << this->name() << endl);
495  s->push(static_cast<BaseType *>(this));
496  }
497  return agg_ptr->var(field, true, s); // recurse
498  }
499  else
500  return 0; // qualified names must be *fully* qualified
501  }
502 
503  return 0;
504 }
505 
506 #if FILE_METHODS
507 void
508 Structure::print_val(FILE *out, string space, bool print_decl_p)
509 {
510  if (print_decl_p) {
511  print_decl(out, space, false);
512  fprintf(out, " = ") ;
513  }
514 
515  fprintf(out, "{ ") ;
516  for (Vars_citer i = _vars.begin(); i != _vars.end();
517  i++, (void)(i != _vars.end() && fprintf(out, ", "))) {
518  (*i)->print_val(out, "", false);
519  }
520 
521  fprintf(out, " }") ;
522 
523  if (print_decl_p)
524  fprintf(out, ";\n") ;
525 }
526 #endif
527 
528 void
529 Structure::print_val(ostream &out, string space, bool print_decl_p)
530 {
531  if (print_decl_p) {
532  print_decl(out, space, false);
533  out << " = " ;
534  }
535 
536  out << "{ " ;
537  for (Vars_citer i = _vars.begin(); i != _vars.end();
538  i++, (void)(i != _vars.end() && out << ", ")) {
539  (*i)->print_val(out, "", false);
540  }
541 
542  out << " }" ;
543 
544  if (print_decl_p)
545  out << ";\n" ;
546 }
547 
548 bool
549 Structure::check_semantics(string &msg, bool all)
550 {
551  if (!BaseType::check_semantics(msg))
552  return false;
553 
554  bool status = true;
555 
556  if (!unique_names(_vars, name(), type_name(), msg))
557  return false;
558 
559  if (all) {
560  for (Vars_iter i = _vars.begin(); i != _vars.end(); i++) {
561  //assert(*i);
562  if (!(*i)->check_semantics(msg, true)) {
563  status = false;
564  goto exit;
565  }
566  }
567  }
568 
569 exit:
570  return status;
571 }
572 
581 void
582 Structure::dump(ostream &strm) const
583 {
584  strm << DapIndent::LMarg << "Structure::dump - ("
585  << (void *)this << ")" << endl ;
587  Constructor::dump(strm) ;
589 }
590 
591 } // namespace libdap
592