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