libdap++  Updated for version 3.8.2
Array.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 Array.
33 //
34 // jhrg 9/13/94
35 
36 
37 #include "config.h"
38 
39 #include "Array.h"
40 #include "util.h"
41 #include "debug.h"
42 #include "InternalErr.h"
43 #include "escaping.h"
44 
45 #include <algorithm>
46 #include <functional>
47 
48 using namespace std;
49 
50 namespace libdap {
51 
52 void
53 Array::_duplicate(const Array &a)
54 {
55  _shape = a._shape;
56 }
57 
58 // The first method of calculating length works when only one dimension is
59 // constrained and you want the others to appear in total. This is important
60 // when selecting from grids since users may not select from all dimensions
61 // in which case that means they want the whole thing. Array projection
62 // should probably work this way too, but it doesn't. 9/21/2001 jhrg
63 
71 void
72 Array::update_length(int)
73 {
74  int length = 1;
75  for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
76  length *= (*i).c_size > 0 ? (*i).c_size : 1;
77  }
78 
79  set_length(length);
80 }
81 
82 // Construct an instance of Array. The (BaseType *) is assumed to be
83 // allocated using new - The dtor for Vector will delete this object.
84 
100 Array::Array(const string &n, BaseType *v) : Vector(n, 0, dods_array_c)
101 {
102  add_var(v); // Vector::add_var() stores null is v is null
103 }
104 
118 Array::Array(const string &n, const string &d, BaseType *v)
119  : Vector(n, d, 0, dods_array_c)
120 {
121  add_var(v); // Vector::add_var() stores null is v is null
122 }
123 
125 Array::Array(const Array &rhs) : Vector(rhs)
126 {
127  _duplicate(rhs);
128 }
129 
132 {
133  DBG(cerr << "Entering ~Array (" << this << ")" << endl);
134  DBG(cerr << "Exiting ~Array" << endl);
135 }
136 
137 BaseType *
139 {
140  return new Array(*this);
141 }
142 
143 Array &
145 {
146  if (this == &rhs)
147  return *this;
148 
149  dynamic_cast<Vector &>(*this) = rhs;
150 
151  _duplicate(rhs);
152 
153  return *this;
154 }
155 
175 void
177 {
178  if (v && v->type() == dods_array_c) {
179  Array &a = dynamic_cast<Array&>(*v);
180  Vector::add_var(a.var());
181  Dim_iter i = a.dim_begin();
182  Dim_iter i_end = a.dim_end();
183  while (i != i_end) {
185  ++i;
186  }
187  }
188  else {
189  Vector::add_var(v);
190  }
191 }
192 
204 void
205 Array::append_dim(int size, string name)
206 {
207  dimension d;
208 
209  // This is invariant
210  d.size = size;
211  d.name = www2id(name);
212 
213  // this information changes with each constraint expression
214  d.start = 0;
215  d.stop = size - 1;
216  d.stride = 1;
217  d.c_size = size;
218 
219  _shape.push_back(d);
220 
221  update_length(size);
222 }
223 
229 void
230 Array::prepend_dim(int size, const string& name/* = "" */)
231 {
232  dimension d;
233 
234  // This is invariant
235  d.size = size;
236  d.name = www2id(name);
237 
238  // this information changes with each constraint expression
239  d.start = 0;
240  d.stop = size - 1;
241  d.stride = 1;
242  d.c_size = size;
243 
244  // Shifts the whole array, but it's tiny in general
245  _shape.insert(_shape.begin(), d);
246 
247  update_length(size); // the number is ignored...
248 }
249 
256 void
258 {
259  set_length(-1);
260 
261  for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
262  (*i).start = 0;
263  (*i).stop = (*i).size - 1;
264  (*i).stride = 1;
265  (*i).c_size = (*i).size;
266 
267  update_length((*i).size);
268  }
269 }
270 
271 
281 void
283 {
285 }
286 
287 // Note: MS VC++ won't tolerate embedded newlines in strings, hence the \n
288 // is explicit.
289 static const char *array_sss = \
290 "Invalid constraint parameters: At least one of the start, stride or stop \n\
291 specified do not match the array variable.";
292 
312 void
313 Array::add_constraint(Dim_iter i, int start, int stride, int stop)
314 {
315  dimension &d = *i ;
316 
317  // Check for bad constraints.
318  // Jose Garcia
319  // Usually invalid data for a constraint is the user's mistake
320  // because they build a wrong URL in the client side.
321  if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
322  throw Error(malformed_expr, array_sss);
323 
324  if (((stop - start) / stride + 1) > d.size)
325  throw Error(malformed_expr, array_sss);
326 
327  d.start = start;
328  d.stop = stop;
329  d.stride = stride;
330 
331  d.c_size = (stop - start) / stride + 1;
332 
333  DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
334 
336 }
337 
341 {
342  return _shape.begin() ;
343 }
344 
348 {
349  return _shape.end() ;
350 }
351 
361 unsigned int
362 Array::dimensions(bool /*constrained*/)
363 {
364  unsigned int dim = 0;
365  for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
366  dim++;
367  }
368 
369  return dim;
370 }
371 
389 int
390 Array::dimension_size(Dim_iter i, bool constrained)
391 {
392  int size = 0;
393 
394  if (!_shape.empty()) {
395  if (constrained)
396  size = (*i).c_size;
397  else
398  size = (*i).size;
399  }
400 
401  return size;
402 }
403 
422 int
423 Array::dimension_start(Dim_iter i, bool /*constrained*/)
424 {
425  return (!_shape.empty()) ? (*i).start : 0;
426 }
427 
446 int
447 Array::dimension_stop(Dim_iter i, bool /*constrained*/)
448 {
449  return (!_shape.empty()) ? (*i).stop : 0;
450 }
451 
471 int
472 Array::dimension_stride(Dim_iter i, bool /*constrained*/)
473 {
474  return (!_shape.empty()) ? (*i).stride : 0;
475 }
476 
487 string
489 {
490  // Jose Garcia
491  // Since this method is public, it is possible for a user
492  // to call it before the Array object has been properly set
493  // this will cause an exception which is the user's fault.
494  // (User in this context is the developer of the surrogate library.)
495  if (_shape.empty())
496  throw InternalErr(__FILE__, __LINE__,
497  "*This* array has no dimensions.");
498  return (*i).name;
499 }
500 
501 #if FILE_METHODS
502 
519 void
520 Array::print_decl(FILE *out, string space, bool print_semi,
521  bool constraint_info, bool constrained)
522 {
523  if (constrained && !send_p())
524  return;
525 
526  // print it, but w/o semicolon
527  var()->print_decl(out, space, false, constraint_info, constrained);
528 
529  for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
530  fprintf(out, "[") ;
531  if ((*i).name != "") {
532  fprintf(out, "%s = ", id2www((*i).name).c_str()) ;
533  }
534  if (constrained) {
535  fprintf(out, "%d]", (*i).c_size) ;
536  }
537  else {
538  fprintf(out, "%d]", (*i).size) ;
539  }
540  }
541 
542  if (print_semi) {
543  fprintf(out, ";\n") ;
544  }
545 }
546 #endif
547 
565 void
566 Array::print_decl(ostream &out, string space, bool print_semi,
567  bool constraint_info, bool constrained)
568 {
569  if (constrained && !send_p())
570  return;
571 
572  // print it, but w/o semicolon
573  var()->print_decl(out, space, false, constraint_info, constrained);
574 
575  for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
576  out << "[" ;
577  if ((*i).name != "") {
578  out << id2www((*i).name) << " = " ;
579  }
580  if (constrained) {
581  out << (*i).c_size << "]" ;
582  }
583  else {
584  out << (*i).size << "]" ;
585  }
586  }
587 
588  if (print_semi) {
589  out << ";\n" ;
590  }
591 }
592 #if FILE_METHODS
593 void
594 Array::print_xml(FILE *out, string space, bool constrained)
595 {
596  print_xml_core(out, space, constrained, "Array");
597 }
598 #endif
599 void
600 Array::print_xml(ostream &out, string space, bool constrained)
601 {
602  print_xml_core(out, space, constrained, "Array");
603 }
604 #if FILE_METHODS
605 void
606 Array::print_as_map_xml(FILE *out, string space, bool constrained)
607 {
608  print_xml_core(out, space, constrained, "Map");
609 }
610 #endif
611 void
612 Array::print_as_map_xml(ostream &out, string space, bool constrained)
613 {
614  print_xml_core(out, space, constrained, "Map");
615 }
616 #if FILE_METHODS
617 class PrintArrayDim : public unary_function<Array::dimension&, void>
618 {
619  FILE *d_out;
620  string d_space;
621  bool d_constrained;
622 public:
623  PrintArrayDim(FILE *o, string s, bool c)
624  : d_out(o), d_space(s), d_constrained(c)
625  {}
626 
627  void operator()(Array::dimension &d)
628  {
629  int size = d_constrained ? d.c_size : d.size;
630  if (d.name.empty())
631  fprintf(d_out, "%s<dimension size=\"%d\"/>\n", d_space.c_str(),
632  size);
633  else
634  fprintf(d_out, "%s<dimension name=\"%s\" size=\"%d\"/>\n",
635  d_space.c_str(), id2xml(d.name).c_str(), size);
636  }
637 };
638 
639 void
640 Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
641 {
642  if (constrained && !send_p())
643  return;
644 
645  fprintf(out, "%s<%s", space.c_str(), tag.c_str());
646  if (!name().empty())
647  fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
648  fprintf(out , ">\n");
649 
650  get_attr_table().print_xml(out, space + " ", constrained);
651 
652  BaseType *btp = var();
653  string tmp_name = btp->name();
654  btp->set_name("");
655  btp->print_xml(out, space + " ", constrained);
656  btp->set_name(tmp_name);
657 
658  for_each(dim_begin(), dim_end(),
659  PrintArrayDim(out, space + " ", constrained));
660 
661  fprintf(out, "%s</%s>\n", space.c_str(), tag.c_str());
662 }
663 #endif
664 
665 class PrintArrayDimStrm : public unary_function<Array::dimension&, void>
666 {
667  ostream &d_out;
668  string d_space;
669  bool d_constrained;
670 public:
671  PrintArrayDimStrm(ostream &o, string s, bool c)
672  : d_out(o), d_space(s), d_constrained(c)
673  {}
674 
675  void operator()(Array::dimension &d)
676  {
677  int size = d_constrained ? d.c_size : d.size;
678  if (d.name.empty())
679  d_out << d_space << "<dimension size=\"" << size << "\"/>\n" ;
680  else
681  d_out << d_space << "<dimension name=\"" << id2xml(d.name)
682  << "\" size=\"" << size << "\"/>\n" ;
683  }
684 };
685 
686 void
687 Array::print_xml_core(ostream &out, string space, bool constrained, string tag)
688 {
689  if (constrained && !send_p())
690  return;
691 
692  out << space << "<" << tag ;
693  if (!name().empty())
694  out << " name=\"" << id2xml(name()) << "\"" ;
695  out << ">\n" ;
696 
697  get_attr_table().print_xml(out, space + " ", constrained);
698 
699  BaseType *btp = var();
700  string tmp_name = btp->name();
701  btp->set_name("");
702  btp->print_xml(out, space + " ", constrained);
703  btp->set_name(tmp_name);
704 
705  for_each(dim_begin(), dim_end(),
706  PrintArrayDimStrm(out, space + " ", constrained));
707 
708  out << space << "</" << tag << ">\n" ;
709 }
710 
711 #if FILE_METHODS
712 
722 unsigned int
723 Array::print_array(FILE *out, unsigned int index, unsigned int dims,
724  unsigned int shape[])
725 {
726  if (dims == 1) {
727  fprintf(out, "{") ;
728  for (unsigned i = 0; i < shape[0] - 1; ++i) {
729  var(index++)->print_val(out, "", false);
730  fprintf(out, ", ") ;
731  }
732  var(index++)->print_val(out, "", false);
733  fprintf(out, "}") ;
734 
735  return index;
736  }
737  else {
738  fprintf(out, "{") ;
739  // Fixed an off-by-one error in the following loop. Since the array
740  // length is shape[dims-1]-1 *and* since we want one less dimension
741  // than that, the correct limit on this loop is shape[dims-2]-1. From
742  // Todd Karakasian.
743  // The saga continues; the loop test should be `i < shape[0]-1'. jhrg
744  // 9/12/96.
745  for (unsigned i = 0; i < shape[0] - 1; ++i) {
746  index = print_array(out, index, dims - 1, shape + 1);
747  fprintf(out, ",") ; // Removed the extra `}'. Also from Todd
748  }
749  index = print_array(out, index, dims - 1, shape + 1);
750  fprintf(out, "}") ;
751 
752  return index;
753  }
754 }
755 #endif
756 
767 unsigned int
768 Array::print_array(ostream &out, unsigned int index, unsigned int dims,
769  unsigned int shape[])
770 {
771  if (dims == 1) {
772  out << "{" ;
773  for (unsigned i = 0; i < shape[0] - 1; ++i) {
774  var(index++)->print_val(out, "", false);
775  out << ", " ;
776  }
777  var(index++)->print_val(out, "", false);
778  out << "}" ;
779 
780  return index;
781  }
782  else {
783  out << "{" ;
784  // Fixed an off-by-one error in the following loop. Since the array
785  // length is shape[dims-1]-1 *and* since we want one less dimension
786  // than that, the correct limit on this loop is shape[dims-2]-1. From
787  // Todd Karakasian.
788  // The saga continues; the loop test should be `i < shape[0]-1'. jhrg
789  // 9/12/96.
790  for (unsigned i = 0; i < shape[0] - 1; ++i) {
791  index = print_array(out, index, dims - 1, shape + 1);
792  out << "," ;
793  }
794  index = print_array(out, index, dims - 1, shape + 1);
795  out << "}" ;
796 
797  return index;
798  }
799 }
800 
801 #if FILE_METHODS
802 void
803 Array::print_val(FILE *out, string space, bool print_decl_p)
804 {
805  // print the declaration if print decl is true.
806  // for each dimension,
807  // for each element,
808  // print the array given its shape, number of dimensions.
809  // Add the `;'
810 
811  if (print_decl_p) {
812  print_decl(out, space, false, false, false);
813  fprintf(out, " = ") ;
814  }
815 
816  unsigned int *shape = new unsigned int[_shape.size()];
817  unsigned int index = 0;
818  for (Dim_iter i = _shape.begin(); i != _shape.end() && index < _shape.size(); i++)
819  shape[index++] = dimension_size(i, true);
820 
821  print_array(out, 0, _shape.size(), shape);
822 
823  delete [] shape; shape = 0;
824 
825  if (print_decl_p) {
826  fprintf(out, ";\n") ;
827  }
828 }
829 #endif
830 
831 void
832 Array::print_val(ostream &out, string space, bool print_decl_p)
833 {
834  // print the declaration if print decl is true.
835  // for each dimension,
836  // for each element,
837  // print the array given its shape, number of dimensions.
838  // Add the `;'
839 
840  if (print_decl_p) {
841  print_decl(out, space, false, false, false);
842  out << " = " ;
843  }
844 
845  unsigned int *shape = new unsigned int[dimensions(true)];
846  unsigned int index = 0;
847  for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
848  shape[index++] = dimension_size(i, true);
849 
850  print_array(out, 0, dimensions(true), shape);
851 
852  delete [] shape; shape = 0;
853 
854  if (print_decl_p) {
855  out << ";\n" ;
856  }
857 }
858 
868 bool
869 Array::check_semantics(string &msg, bool)
870 {
871  bool sem = BaseType::check_semantics(msg) && !_shape.empty();
872 
873  if (!sem)
874  msg = "An array variable must have dimensions";
875 
876  return sem;
877 }
878 
887 void
888 Array::dump(ostream &strm) const
889 {
890  strm << DapIndent::LMarg << "Array::dump - ("
891  << (void *)this << ")" << endl ;
893  Vector::dump(strm) ;
894  strm << DapIndent::LMarg << "shape:" << endl ;
896  Dim_citer i = _shape.begin() ;
897  Dim_citer ie = _shape.end() ;
898  unsigned int dim_num = 0 ;
899  for (; i != ie; i++) {
900  strm << DapIndent::LMarg << "dimension " << dim_num++ << ":"
901  << endl ;
903  strm << DapIndent::LMarg << "name: " << (*i).name << endl ;
904  strm << DapIndent::LMarg << "size: " << (*i).size << endl ;
905  strm << DapIndent::LMarg << "start: " << (*i).start << endl ;
906  strm << DapIndent::LMarg << "stop: " << (*i).stop << endl ;
907  strm << DapIndent::LMarg << "stride: " << (*i).stride << endl ;
908  strm << DapIndent::LMarg << "constrained size: " << (*i).c_size
909  << endl ;
911  }
914 }
915 
916 } // namespace libdap
917 
virtual void reset_constraint()
Reset constraint to select entire array.
Definition: Array.cc:257
virtual void add_constraint(Dim_iter i, int start, int stride, int stop)
Adds a constraint to an Array dimension.
Definition: Array.cc:313
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:210
virtual bool check_semantics(string &msg, bool all=false)
Check semantic features of the Array.
Definition: Array.cc:869
virtual void print_xml_core(FILE *out, string space, bool constrained, string tag)
Definition: Array.cc:640
static void UnIndent()
Definition: DapIndent.cc:49
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Array.cc:888
virtual void print_decl(FILE *out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Print an ASCII representation of the variable structure.
Definition: BaseType.cc:853
virtual unsigned int dimensions(bool constrained=false)
Return the total number of dimensions in the array.
Definition: Array.cc:362
virtual void print_xml(FILE *out, string space=" ", bool constrained=false)
Definition: BaseType.cc:948
Part
Names the parts of multi-section constructor data types.
Definition: BaseType.h:98
void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
Definition: Array.cc:176
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:217
int stop
The constraint end index.
Definition: Array.h:119
#define malformed_expr
Definition: Error.h:64
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:78
std::vector< dimension >::const_iterator Dim_citer
Definition: Array.h:145
virtual void print_xml(FILE *out, string pad=" ", bool constrained=false)
Definition: AttrTable.cc:1209
int start
The constraint start index.
Definition: Array.h:118
string id2xml(string in, const string &not_allowed)
Definition: escaping.cc:266
Array & operator=(const Array &rhs)
Definition: Array.cc:144
virtual void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
Definition: Vector.cc:1543
void _duplicate(const Array &a)
Definition: Array.cc:53
A class for software fault reporting.
Definition: InternalErr.h:64
Dim_iter dim_end()
Definition: Array.cc:347
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:383
virtual void print_as_map_xml(ostream &out, string space=" ", bool constrained=false)
Definition: Array.cc:612
#define DBG(x)
Definition: debug.h:58
virtual int dimension_size(Dim_iter i, bool constrained=false)
Returns the size of the dimension.
Definition: Array.cc:390
static void Indent()
Definition: DapIndent.cc:43
void append_dim(int size, string name="")
Add a dimension of a given size.
Definition: Array.cc:205
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
std::vector< dimension >::iterator Dim_iter
Definition: Array.h:152
virtual string dimension_name(Dim_iter i)
Returns the name of the specified dimension.
Definition: Array.cc:488
virtual BaseType * ptr_duplicate()
Definition: Array.cc:138
virtual int dimension_stride(Dim_iter i, bool constrained=false)
Returns the stride value of the constraint.
Definition: Array.cc:472
int stride
The constraint stride.
Definition: Array.h:120
virtual void print_decl(ostream &out, string space=" ", bool print_semi=true, bool constraint_info=false, bool constrained=false)
Prints a DDS entry for the Array.
Definition: Array.cc:566
int c_size
Size of dimension once constrained.
Definition: Array.h:121
void prepend_dim(int size, const string &name="")
Definition: Array.cc:230
virtual void print_xml(ostream &out, string space=" ", bool constrained=false)
Definition: Array.cc:600
Array(const string &n, BaseType *v)
Array constructor.
Definition: Array.cc:100
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:214
virtual int dimension_stop(Dim_iter i, bool constrained=false)
Return the stop index of the constraint.
Definition: Array.cc:447
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual int dimension_start(Dim_iter i, bool constrained=false)
Return the start index of a dimension.
Definition: Array.cc:423
virtual AttrTable & get_attr_table()
Definition: BaseType.cc:531
virtual ~Array()
The Array destructor.
Definition: Array.cc:131
int size
The unconstrained dimension size.
Definition: Array.h:116
string name
The name of this dimension.
Definition: Array.h:117
The basic data type for the DODS DAP types.
Definition: BaseType.h:190
Dim_iter dim_begin()
Definition: Array.cc:340
virtual void update_length(int size)
Definition: Array.cc:72
virtual void set_length(int l)
Definition: Vector.cc:535
A class for error processing.
Definition: Error.h:90
unsigned int print_array(FILE *out, unsigned int index, unsigned int dims, unsigned int shape[])
Print the value given the current constraint.
Definition: Array.cc:723
A multidimensional array of identical data types.
Definition: Array.h:101
virtual void print_val(ostream &out, string space="", bool print_decl_p=true)
Prints the value of the variable.
Definition: Array.cc:832
virtual bool send_p()
Should this variable be sent?
Definition: BaseType.cc:503
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Vector.cc:1591
string id2www(string in, const string &allowable)
Definition: escaping.cc:151
virtual void print_val(FILE *out, string space="", bool print_decl_p=true)=0
Prints the value of the variable.
virtual void clear_constraint()
Clears the projection; add each projected dimension explicitly using add_constraint.
Definition: Array.cc:282
virtual bool check_semantics(string &msg, bool all=false)
Compare an object&#39;s current state with the semantics of its type.
Definition: BaseType.cc:1036