libdap++  Updated for version 3.8.2
Vector.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 1995-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 class Vector. This class is the basis for all the
33 // vector-type classes in libdap's <Array, List>.
34 //
35 // 11/21/95 jhrg
36 
37 #include "config.h"
38 
39 #include <cstring>
40 
41 static char rcsid[] not_used =
42  { "$Id: Vector.cc 24281 2011-03-09 00:22:31Z jimg $"
43  };
44 
45 //#define DODS_DEBUG
46 
47 #include <algorithm>
48 
49 #include "Vector.h"
50 #include "escaping.h"
51 #include "util.h"
52 #include "debug.h"
53 #include "InternalErr.h"
54 #include <sstream>
55 
56 using std::cerr;
57 using std::endl;
58 
59 namespace libdap {
60 
61 void Vector::_duplicate(const Vector & v)
62 {
63  _length = v._length;
64 
65  // _var holds the type of the elements. That is, it holds a BaseType
66  // which acts as a template for the type of each element.
67  if (v._var) {
68  _var = v._var->ptr_duplicate(); // use ptr_duplicate()
69  _var->set_parent(this); // ptr_duplicate does not set d_parent.
70  }
71  else {
72  _var = 0;
73  }
74 
75  // _vec and _buf (further down) hold the values of the Vector. The field
76  // _vec is used when the Vector holds non-numeric data (including strings
77  // although it used to be that was not the case jhrg 2/10/05) while _buf
78  // holds numeric values.
79  if (v._vec.empty()) {
80  _vec = v._vec;
81  }
82  else {
83  // Failure to set the size will make the [] operator barf on the LHS
84  // of the assignment inside the loop.
85  _vec.resize(_length);
86  for (int i = 0; i < _length; ++i) {
87  // There's no need to call set_parent() for each element; we
88  // maintain the back pointer using the _var member. These
89  // instances are used to hold _values_ only while the _var
90  // field holds the type of the elements.
91  _vec[i] = v._vec[i]->ptr_duplicate();
92  }
93  }
94 
95  // copy the strings. This copies the values.
96  d_str = v.d_str;
97 
98  // copy numeric values if there are any.
99  _buf = 0; // init to null
100  if (v._buf) // only copy if data present
101  val2buf(v._buf); // store v's value in this's _BUF.
102 
103  _capacity = v._capacity;
104 }
105 
110 bool
112 {
113  // Not cardinal if no _var at all!
114  if (!_var) {
115  return false;
116  }
117 
118  switch (_var->type()) {
119  case dods_byte_c:
120  case dods_int16_c:
121  case dods_uint16_c:
122  case dods_int32_c:
123  case dods_uint32_c:
124  case dods_float32_c:
125  case dods_float64_c: {
126  return true;
127  break;
128  }
129 
130  // These must be handled differently.
131  case dods_str_c:
132  case dods_url_c:
133  case dods_array_c:
134  case dods_structure_c:
135  case dods_sequence_c:
136  case dods_grid_c:
137  return false;
138  break;
139 
140  default:
141  cerr << "Vector::var: Unrecognized type" << endl;
142  return false;
143  } // switch
144 }
145 
158 unsigned int
160 {
161  // Make sure we HAVE a _var, or we cannot continue.
162  if (!_var) {
163  throw InternalErr(__FILE__, __LINE__,
164  "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
165  }
166 
167  // Make sure we only do this for the correct data types.
168  if (!is_cardinal_type()) {
169  throw InternalErr(__FILE__, __LINE__,
170  "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
171  }
172 
174 
175  // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
176  unsigned int bytesPerElt = _var->width();
177  unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
178  _buf = new char[bytesNeeded];
179  if (!_buf) {
180  ostringstream oss;
181  oss << "create_cardinal_data_buffer_for_type: new char[] failed to allocate " <<
182  bytesNeeded <<
183  " bytes! Out of memory or too large a buffer required!";
184  throw InternalErr(__FILE__, __LINE__, oss.str());
185  }
186  _capacity = numEltsOfType;
187  return bytesNeeded;
188 }
189 
191 void
193 {
194  if (_buf) {
195  delete[] _buf;
196  _buf = 0;
197  _capacity = 0;
198  }
199 }
200 
204 template <class CardType>
205 void
206 Vector::set_cardinal_values_internal(const CardType* fromArray, int numElts)
207 {
208  if (numElts < 0) {
209  throw InternalErr(__FILE__, __LINE__,
210  "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
211  }
212  if (!fromArray) {
213  throw InternalErr(__FILE__, __LINE__,
214  "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
215  }
216  set_length(numElts);
218  memcpy(_buf, fromArray, numElts * sizeof(CardType) );
219  set_read_p(true);
220 }
221 
222 
239 Vector::Vector(const string & n, BaseType * v, const Type & t)
240  : BaseType(n, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
241 {
242  if (v)
243  add_var(v);
244 
245  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
246  if (_var)
247  _var->set_parent(this);
248 }
249 
269 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t)
270  : BaseType(n, d, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
271 {
272  if (v)
273  add_var(v);
274 
275  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
276  if (_var)
277  _var->set_parent(this);
278 }
279 
281 Vector::Vector(const Vector & rhs): BaseType(rhs)
282 {
283  DBG2(cerr << "Entering Vector const ctor for object: " << this <<
284  endl);
285  DBG2(cerr << "RHS: " << &rhs << endl);
286 
287  _duplicate(rhs);
288 }
289 
291 {
292  DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
293 
294  delete _var;
295  _var = 0;
296 
297  // Clears all buffers
299 
300  DBG2(cerr << "Exiting ~Vector" << endl);
301 }
302 
304 {
305  if (this == &rhs)
306  return *this;
307 
308  dynamic_cast < BaseType & >(*this) = rhs;
309 
310  _duplicate(rhs);
311 
312  return *this;
313 }
314 
315 void
316 Vector::set_name(const std::string& name)
317 {
318  BaseType::set_name(name);
319  // We need to set the template variable name as well since
320  // this is what gets output in the dds! Otherwise, there's a mismatch.
321  if (_var) {
322  _var->set_name(name);
323  }
324 }
325 
326 int Vector::element_count(bool leaves)
327 {
328  if (!leaves)
329  return 1;
330  else
331  // var() only works for simple types!
332  return var(0)->element_count(leaves);
333 }
334 
335 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
336 // from BaseType's version in that they set both the Vector object's copy of
337 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
338 // is a scalar, but does matter when it is an aggregate.
339 
346 void Vector::set_send_p(bool state)
347 {
348  _var->set_send_p(state);
349  BaseType::set_send_p(state);
350 }
351 
358 void Vector::set_read_p(bool state)
359 {
360  if (_var) {
361  _var->set_read_p(state);
362  }
363  BaseType::set_read_p(state);
364 }
365 
383 BaseType *Vector::var(const string & n, bool exact, btp_stack * s)
384 {
385  string name = www2id(n);
386  DBG(cerr << "Vector::var: Looking for " << n << endl);
387 
388  // Make sure to check for the case where name is the default (the empty
389  // string). 9/1/98 jhrg
390  if (_var->is_constructor_type()) {
391  if (name == "" || _var->name() == name) {
392  if (s)
393  s->push(this);
394  return _var;
395  }
396  else {
397  BaseType * result = _var->var(name, exact, s);
398  if (result && s)
399  s->push(this);
400  return result;
401  }
402  }
403  else {
404  return _var; // I don't see why this isn't return 0 *** jhrg 10/9/08
405  }
406 }
407 
418 BaseType *Vector::var(const string & n, btp_stack & s)
419 {
420  string name = www2id(n);
421 
422  if (_var->is_constructor_type())
423  return _var->var(name, s);
424  else {
425  s.push((BaseType *) this);
426  return _var;
427  }
428 }
429 
430 // Return a pointer the the BaseType object for element I. If the Vector is
431 // of a cardinal type, store the ith element's value in the BaseType
432 // object. If it is a Vector of a non-cardinal type, then this mfunc returns
433 // _vec[i].
434 //
435 // NB: I defaults to zero.
436 //
437 // Returns: A BaseType pointer to the ith element of the Vector.
438 
454 BaseType *Vector::var(unsigned int i)
455 {
456 
457  switch (_var->type()) {
458  case dods_byte_c:
459  case dods_int16_c:
460  case dods_uint16_c:
461  case dods_int32_c:
462  case dods_uint32_c:
463  case dods_float32_c:
464  case dods_float64_c: {
465  // Transfer the ith value to the BaseType *_var; There are more
466  // efficient ways to get a whole array using buf2val() but this is
467  // an OK way to get a single value or several non-contiguous values.
468  unsigned int sz = _var->width();
469  _var->val2buf((char *) _buf + (i * sz));
470  return _var;
471  break;
472  }
473 
474  case dods_str_c:
475  case dods_url_c:
476  _var->val2buf(&d_str[i]);
477  return _var;
478  break;
479 
480  case dods_array_c:
481  case dods_structure_c:
482  case dods_sequence_c:
483  case dods_grid_c:
484  return _vec[i];
485  break;
486 
487  default:
488  cerr << "Vector::var: Unrecognized type" << endl;
489  }
490 
491  return 0;
492 }
493 
494 // Return: The number of bytes required to store the vector `in a C
495 // program'. For an array of cardinal types this is the same as the storage
496 // used by _BUF. For anything else, it is the product of length() and the
497 // element width(). It turns out that both values can be computed the same
498 // way.
499 //
500 // Returns: The number of bytes used to store the vector.
501 
507 unsigned int Vector::width()
508 {
509  // Jose Garcia
510  if (!_var) {
511  throw InternalErr(__FILE__, __LINE__,
512  "Cannot get width since *this* object is not holding data.");
513  }
514 
515  return length() * _var->width();
516 }
517 
518 // Returns: the number of elements in the vector.
519 
524 int Vector::length() const
525 {
526  return _length;
527 }
528 
529 // set the number of elements in the vector.
530 //
531 // Returns: void
532 
536 {
537  _length = l;
538 }
539 
540 // \e l is the number of elements the vector can hold (e.g., if l == 20, then
541 // the vector can hold elements 0, .., 19).
542 
549 {
550  _vec.resize((l > 0) ? l : 0, 0); // Fill with NULLs
551  _capacity = l; // capacity in terms of number of elements.
552 }
553 
569 void
571 {
572  DBG(cerr << "Vector::intern_data: " << name() << endl);
573  if (!read_p())
574  read(); // read() throws Error and InternalErr
575 
576  // length() is not capacity; it must be set explicitly in read().
577  int num = length();
578 
579  switch (_var->type()) {
580  case dods_byte_c:
581  case dods_int16_c:
582  case dods_uint16_c:
583  case dods_int32_c:
584  case dods_uint32_c:
585  case dods_float32_c:
586  case dods_float64_c:
587  // For these cases, read() puts the data into _buf, which is what we
588  // need to do 'stuff' with the data.
589  break;
590 
591  case dods_str_c:
592  case dods_url_c:
593  // For these cases, read() will put the data into d_str[], which is
594  // what the transformation classes need.
595  break;
596 
597  case dods_array_c:
598  // I think this is an error since there can never be an Array of
599  // Array.
600  throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
601  break;
602 
603  case dods_structure_c:
604  case dods_sequence_c:
605  case dods_grid_c:
606  DBG(cerr << "Vector::intern_data: found ctor" << endl);
607  // For these cases, we need to call read() for each of the 'num'
608  // elements in the '_vec[]' array of BaseType object pointers.
609  if (_vec.capacity() == 0)
610  throw InternalErr(__FILE__, __LINE__,
611  "The capacity of *this* vector is 0.");
612 
613  for (int i = 0; i < num; ++i)
614  _vec[i]->intern_data(eval, dds);
615 
616  break;
617 
618  default:
619  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
620  break;
621  }
622 }
623 
637  Marshaller &m, bool ce_eval)
638 {
639  int i = 0;
640 
641  dds.timeout_on();
642 
643  if (!read_p())
644  read(); // read() throws Error and InternalErr
645 
646 #if EVAL
647  if (ce_eval && !eval.eval_selection(dds, dataset()))
648  return true;
649 #endif
650 
651  dds.timeout_off();
652 
653  // length() is not capacity; it must be set explicitly in read().
654  int num = length();
655 
656  switch (_var->type()) {
657  case dods_byte_c:
658  m.put_vector( _buf, num, *this ) ;
659  break ;
660  case dods_int16_c:
661  case dods_uint16_c:
662  case dods_int32_c:
663  case dods_uint32_c:
664  case dods_float32_c:
665  case dods_float64_c:
666  m.put_vector( _buf, num, _var->width(), *this ) ;
667  break;
668 
669  case dods_str_c:
670  case dods_url_c:
671  if (d_str.capacity() == 0)
672  throw InternalErr(__FILE__, __LINE__,
673  "The capacity of the string vector is 0");
674 
675  m.put_int( num ) ;
676 
677  for (i = 0; i < num; ++i)
678  m.put_str( d_str[i] ) ;
679 
680  break;
681 
682  case dods_array_c:
683  case dods_structure_c:
684  case dods_sequence_c:
685  case dods_grid_c:
686  //Jose Garcia
687  // Not setting the capacity of _vec is an internal error.
688  if (_vec.capacity() == 0)
689  throw InternalErr(__FILE__, __LINE__,
690  "The capacity of *this* vector is 0.");
691 
692  m.put_int( num ) ;
693 
694  for (i = 0; i < num; ++i)
695  _vec[i]->serialize(eval, dds, m, false);
696 
697  break;
698 
699  default:
700  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
701  break;
702  }
703 
704  return true;
705 }
706 
707 // Read an object from the network and internalize it. For a Vector this is
708 // handled differently for a `cardinal' type. Vectors of Cardinals are
709 // stored using the `C' representations because these objects often are used
710 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
711 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
712 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
713 // Grid are vectors of the libdap Structure, ... classes).
714 //
715 // The boolean parameter REUSE determines whether internal storage is reused
716 // or not. If true, the _buf member is assumed to be large enough to hold the
717 // incoming cardinal data and is *not* reallocated. If false, new storage is
718 // allocated. If the internal buffer has not yet been allocated, then this
719 // parameter has no effect (i.e., storage is allocated). This parameter
720 // effects storage for cardinal data only.
721 //
722 // Returns: True is successful, false otherwise.
723 
724 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
725 {
726  unsigned int num;
727  unsigned i = 0;
728 
729  switch (_var->type()) {
730  case dods_byte_c:
731  case dods_int16_c:
732  case dods_uint16_c:
733  case dods_int32_c:
734  case dods_uint32_c:
735  case dods_float32_c:
736  case dods_float64_c:
737  if (_buf && !reuse) {
739  }
740 
741  um.get_int( (int &)num ) ;
742 
743  DBG(cerr << "Vector::deserialize: num = " << num << endl);
744  DBG(cerr << "Vector::deserialize: length = " << length() << endl);
745 
746  if (length() == -1)
747  set_length(num);
748 
749  if (num != (unsigned int) length())
750  throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes.");
751 
752  if (!_buf) {
753  // Make _buf be large enough for length() elements of _var->type()
755  DBG(cerr << "Vector::deserialize: allocating "
756  << width() << " bytes for an array of "
757  << length() << " " << _var->type_name() << endl);
758  }
759 
760  if (_var->type() == dods_byte_c)
761  um.get_vector( (char **)&_buf, num, *this ) ;
762  else
763  um.get_vector( (char **)&_buf, num, _var->width(), *this ) ;
764 
765  DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
766 
767  break;
768 
769  case dods_str_c:
770  case dods_url_c:
771  um.get_int( (int &)num ) ;
772 
773  if (length() == -1)
774  set_length(num);
775 
776  if (num != (unsigned int) length())
777  throw InternalErr(__FILE__, __LINE__,
778  "The client sent declarations and data with mismatched sizes.");
779 
780  d_str.resize((num > 0) ? num : 0); // Fill with NULLs
781  _capacity = num; // capacity is number of strings we can fit.
782 
783  for (i = 0; i < num; ++i) {
784  string str;
785  um.get_str( str ) ;
786  d_str[i] = str;
787 
788  }
789 
790  break;
791 
792  case dods_array_c:
793  case dods_structure_c:
794  case dods_sequence_c:
795  case dods_grid_c:
796  um.get_int( (int &)num ) ;
797 
798  if (length() == -1)
799  set_length(num);
800 
801  if (num != (unsigned int) length())
802  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
803 
804  vec_resize(num);
805 
806  for (i = 0; i < num; ++i) {
807  _vec[i] = _var->ptr_duplicate();
808  _vec[i]->deserialize(um, dds);
809  }
810 
811  break;
812 
813  default:
814  throw InternalErr(__FILE__, __LINE__, "Unknown type!");
815  break;
816  }
817 
818  return false;
819 }
820 
848 unsigned int Vector::val2buf(void *val, bool reuse)
849 {
850  // Jose Garcia
851 
852  // I *think* this method has been mainly designed to be use by read which
853  // is implemented in the surrogate library. Passing NULL as a pointer to
854  // this method will be an error of the creator of the surrogate library.
855  // Even though I recognize the fact that some methods inside libdap++ can
856  // call val2buf, I think by now no coding bugs such as misusing val2buf
857  // will be in libdap++, so it will be an internal error from the
858  // surrogate library.
859  if (!val)
860  throw InternalErr(__FILE__, __LINE__,
861  "The incoming pointer does not contain any data.");
862 
863  switch (_var->type()) {
864  case dods_byte_c:
865  case dods_int16_c:
866  case dods_uint16_c:
867  case dods_int32_c:
868  case dods_uint32_c:
869  case dods_float32_c:
870  case dods_float64_c: {
871  // width() returns the size given the constraint
872  unsigned int array_wid = width();
873  if (_buf && !reuse) {
875  }
876 
877  if (!_buf) { // First time or no reuse (free'd above)
879  }
880 
881  memcpy(_buf, val, array_wid);
882  break;
883  }
884 
885  case dods_str_c:
886  case dods_url_c: {
887  // Assume val points to an array of C++ string objects. Copy
888  // them into the vector<string> field of this object.
889  d_str.resize(_length);
890  _capacity = _length;
891  for (int i = 0; i < _length; ++i)
892  d_str[i] = *(static_cast < string * >(val) + i);
893 
894  break;
895  }
896 
897  default:
898  throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
899 
900  }
901 
902  return width();
903 }
904 
935 unsigned int Vector::buf2val(void **val)
936 {
937  // Jose Garcia
938  // The same comment in Vector::val2buf applies here!
939  if (!val)
940  throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
941 
942  unsigned int wid = static_cast<unsigned int>(width());
943  // This is the width computed using length(). The
944  // length() property is changed when a projection
945  // constraint is applied. Thus this is the number of
946  // bytes in the buffer given the current constraint.
947 
948  switch (_var->type()) {
949  case dods_byte_c:
950  case dods_int16_c:
951  case dods_uint16_c:
952  case dods_int32_c:
953  case dods_uint32_c:
954  case dods_float32_c:
955  case dods_float64_c:
956  if (!*val) {
957  *val = new char[wid];
958  }
959  // avoid bus error if _buf is null and this is called improperly.
960  if (!_buf) {
961  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when _buf was null!");
962  }
963 
964  (void) memcpy(*val, _buf, wid);
965 
966  break;
967 
968  case dods_str_c:
969  case dods_url_c: {
970  if (!*val)
971  *val = new string[_length];
972 
973  for (int i = 0; i < _length; ++i)
974  *(static_cast < string * >(*val) + i) = d_str[i];
975 
976  break;
977  }
978 
979  default:
980  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
981  return 0;
982  }
983 
984  return wid;
985 }
986 
1007 void Vector::set_vec(unsigned int i, BaseType * val)
1008 {
1009  // Jose Garcia
1010  // This is a public method which allows users to set the elements
1011  // of *this* vector. Passing an invalid index, a NULL pointer or
1012  // mismatching the vector type are internal errors.
1013  if (i >= static_cast < unsigned int >(_length))
1014  throw InternalErr(__FILE__, __LINE__,
1015  "Invalid data: index too large.");
1016  if (!val)
1017  throw InternalErr(__FILE__, __LINE__,
1018  "Invalid data: null pointer to BaseType object.");
1019  if (val->type() != _var->type())
1020  throw InternalErr(__FILE__, __LINE__,
1021  "invalid data: type of incoming object does not match *this* vector type.");
1022 
1023  if (i >= _vec.capacity())
1024  vec_resize(i + 10);
1025 
1026  _vec[i] = val->ptr_duplicate();
1027 }
1028 
1038 void
1040 {
1041  if (_buf) {
1042  delete[]_buf;
1043  _buf = 0;
1044  }
1045 
1046  for (unsigned int i = 0; i < _vec.size(); ++i) {
1047  delete _vec[i];
1048  _vec[i] = 0;
1049  }
1050 
1051  // Force memory to be reclaimed.
1052  _vec.resize(0);
1053  d_str.resize(0);
1054 
1055  _capacity = 0;
1056  set_read_p(false);
1057 }
1058 
1059 
1067 unsigned int
1069 {
1070  return _capacity;
1071 }
1072 
1073 
1083 void
1084 Vector::reserve_value_capacity(unsigned int numElements)
1085 {
1086  if (!_var) {
1087  throw InternalErr(__FILE__, __LINE__,
1088  "reserve_value_capacity: Logic error: _var is null!");
1089  }
1090  switch (_var->type()) {
1091  case dods_byte_c:
1092  case dods_int16_c:
1093  case dods_uint16_c:
1094  case dods_int32_c:
1095  case dods_uint32_c:
1096  case dods_float32_c:
1097  case dods_float64_c: {
1098  // Make _buf be the right size and set _capacity
1100  }
1101  break;
1102 
1103  case dods_str_c:
1104  case dods_url_c: {
1105  // Make sure the d_str has enough room for all the strings.
1106  // Technically not needed, but it will speed things up for large arrays.
1107  d_str.reserve(numElements);
1108  _capacity = numElements;
1109  }
1110  break;
1111 
1112 
1113  case dods_array_c:
1114  case dods_structure_c:
1115  case dods_sequence_c:
1116  case dods_grid_c: {
1117  // not clear anyone will go this path, but best to be complete.
1118  _vec.reserve(numElements);
1119  _capacity = numElements;
1120  }
1121  break;
1122 
1123  default: {
1124  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1125  }
1126  break;
1127 
1128  } // switch
1129 
1130 }
1131 
1137 void
1139 {
1140  // Use the current length of the vector as the reserve amount.
1142 }
1143 
1172 unsigned int
1173 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1174 {
1175  static const string funcName = "set_value_slice_from_row_major_vector:";
1176 
1177  // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1178  Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1179 
1180  bool typesMatch = rowMajorData.var() && _var && (rowMajorData.var()->type() == _var->type());
1181  if (!typesMatch) {
1182  throw InternalErr(__FILE__, __LINE__,
1183  funcName + "Logic error: types do not match so cannot be copied!");
1184  }
1185 
1186  // Make sure the data exists
1187  if (!rowMajorData.read_p()) {
1188  throw InternalErr(__FILE__, __LINE__,
1189  funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1190  }
1191 
1192  // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1193  if (rowMajorData.length() < 0) {
1194  throw InternalErr(__FILE__, __LINE__,
1195  funcName + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1196  }
1197 
1198  // The read-in capacity had better be at least the length (the amountt we will copy) or we'll memcpy into bad memory
1199  // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1200  if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1201  throw InternalErr(__FILE__, __LINE__,
1202  funcName + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1203  }
1204 
1205  // Make sure there's enough room in this Vector to store all the elements requested. Again,
1206  // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1207  if (_capacity < (startElement + rowMajorData.length())) {
1208  throw InternalErr(__FILE__, __LINE__,
1209  funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1210  }
1211 
1212  // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1213  switch (_var->type()) {
1214  case dods_byte_c:
1215  case dods_int16_c:
1216  case dods_uint16_c:
1217  case dods_int32_c:
1218  case dods_uint32_c:
1219  case dods_float32_c:
1220  case dods_float64_c: {
1221  if (!_buf) {
1222  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1223  }
1224  if (!rowMajorData._buf) {
1225  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1226  }
1227  // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1228  int varWidth = _var->width();
1229  char* pFromBuf = rowMajorData._buf;
1230  int numBytesToCopy = rowMajorData.width();
1231  char* pIntoBuf = _buf + (startElement * varWidth);
1232  memcpy(pIntoBuf,
1233  pFromBuf,
1234  numBytesToCopy );
1235  }
1236  break;
1237 
1238  case dods_str_c:
1239  case dods_url_c: {
1240  // Strings need to be copied directly
1241  for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1242  d_str[startElement + i] = rowMajorData.d_str[i];
1243  }
1244  }
1245  break;
1246 
1247  case dods_array_c:
1248  case dods_structure_c:
1249  case dods_sequence_c:
1250  case dods_grid_c: {
1251  // Not sure that this function will be used for these type of nested objects, so I will throw here.
1252  // TODO impl and test this path if it's ever needed.
1253  throw InternalErr(__FILE__, __LINE__,
1254  funcName + "Unimplemented method for Vectors of type: dods_array_c, dods_structure_c, dods_sequence_c and dods_grid_c.");
1255  }
1256  break;
1257 
1258  default: {
1259  throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1260  }
1261  break;
1262 
1263  } // switch (_var->type())
1264 
1265  // This is how many elements we copied.
1266  return (unsigned int)rowMajorData.length();
1267 }
1268 
1270 
1271 bool
1273 {
1274  if (var()->type() == dods_byte_c && val) {
1275  set_cardinal_values_internal<dods_byte>(val, sz);
1276  return true;
1277  }
1278  else {
1279  return false;
1280  }
1281 }
1282 
1284 bool
1285 Vector::set_value(vector<dods_byte> &val, int sz)
1286 {
1287  return set_value(&val[0], sz);
1288 }
1289 
1291 bool
1293 {
1294  if (var()->type() == dods_int16_c && val) {
1295  set_cardinal_values_internal<dods_int16>(val, sz);
1296  return true;
1297  }
1298  else {
1299  return false;
1300  }
1301 }
1302 
1304 bool
1305 Vector::set_value(vector<dods_int16> &val, int sz)
1306 {
1307  return set_value(&val[0], sz);
1308 }
1309 
1311 bool
1313 {
1314  if (var()->type() == dods_int32_c && val) {
1315  set_cardinal_values_internal<dods_int32>(val, sz);
1316  return true;
1317  }
1318  else {
1319  return false;
1320  }
1321 }
1322 
1324 bool
1325 Vector::set_value(vector<dods_int32> &val, int sz)
1326 {
1327  return set_value(&val[0], sz);
1328 }
1329 
1331 bool
1333 {
1334  if (var()->type() == dods_uint16_c && val) {
1335  set_cardinal_values_internal<dods_uint16>(val, sz);
1336  return true;
1337  }
1338  else {
1339  return false;
1340  }
1341 }
1342 
1344 bool
1345 Vector::set_value(vector<dods_uint16> &val, int sz)
1346 {
1347  return set_value(&val[0], sz);
1348 }
1349 
1351 bool
1353 {
1354  if (var()->type() == dods_uint32_c && val) {
1355  set_cardinal_values_internal<dods_uint32>(val, sz);
1356  return true;
1357  }
1358  else {
1359  return false;
1360  }
1361 }
1362 
1364 bool
1365 Vector::set_value(vector<dods_uint32> &val, int sz)
1366 {
1367  return set_value(&val[0], sz);
1368 }
1369 
1371 bool
1373 {
1374  if (var()->type() == dods_float32_c && val) {
1375  set_cardinal_values_internal<dods_float32>(val, sz);
1376  return true;
1377  }
1378  else {
1379  return false;
1380  }
1381 }
1382 
1384 bool
1385 Vector::set_value(vector<dods_float32> &val, int sz)
1386 {
1387  return set_value(&val[0], sz);
1388 }
1389 
1391 bool
1393 {
1394  if (var()->type() == dods_float64_c && val) {
1395  set_cardinal_values_internal<dods_float64>(val, sz);
1396  return true;
1397  }
1398  else {
1399  return false;
1400  }
1401 }
1402 
1404 bool
1405 Vector::set_value(vector<dods_float64> &val, int sz)
1406 {
1407  return set_value(&val[0], sz);
1408 }
1409 
1411 bool
1412 Vector::set_value(string *val, int sz)
1413 {
1414  if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1415  d_str.resize(sz);
1416  _capacity = sz;
1417  for (register int t = 0; t < sz; t++) {
1418  d_str[t] = val[t] ;
1419  }
1420  set_length(sz) ;
1421  set_read_p(true);
1422  return true;
1423  }
1424  else {
1425  return false;
1426  }
1427 }
1428 
1430 bool
1431 Vector::set_value(vector<string> &val, int sz)
1432 {
1433  if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1434  d_str.resize(sz);
1435  _capacity = sz;
1436  for (register int t = 0; t < sz; t++) {
1437  d_str[t] = val[t] ;
1438  }
1439  set_length(sz) ;
1440  set_read_p(true);
1441  return true;
1442  }
1443  else {
1444  return false;
1445  }
1446 }
1448 
1450 
1457 void Vector::value(dods_byte *b) const
1458 {
1459  if (b && _var->type() == dods_byte_c) {
1460  memcpy(b, _buf, length() * sizeof(dods_byte));
1461  }
1462 }
1463 
1466 {
1467  if (b && _var->type() == dods_uint16_c) {
1468  memcpy(b, _buf, length() * sizeof(dods_uint16));
1469  }
1470 }
1471 
1474 {
1475  if (b && _var->type() == dods_int16_c) {
1476  memcpy(b, _buf, length() * sizeof(dods_int16));
1477  }
1478 }
1479 
1482 {
1483  if (b && _var->type() == dods_uint32_c) {
1484  memcpy(b, _buf, length() * sizeof(dods_uint32));
1485  }
1486 }
1487 
1490 {
1491  if (b && _var->type() == dods_int32_c) {
1492  memcpy(b, _buf, length() * sizeof(dods_int32));
1493  }
1494 }
1495 
1498 {
1499  if (b && _var->type() == dods_float32_c) {
1500  memcpy(b, _buf, length() * sizeof(dods_float32));
1501  }
1502 }
1503 
1506 {
1507  if (b && _var->type() == dods_float64_c) {
1508  memcpy(b, _buf, length() * sizeof(dods_float64));
1509  }
1510 }
1511 
1513 void Vector::value(vector<string> &b) const
1514 {
1515  if (_var->type() == dods_byte_c || _var->type() == dods_url_c)
1516  b = d_str;
1517 }
1518 
1522 {
1523  void *buffer = new char[width()];
1524 
1525  memcpy(buffer, _buf, width());
1526 
1527  return buffer;
1528 }
1530 
1544 {
1545  // Delete the current template variable
1546  if( _var )
1547  {
1548  delete _var;
1549  _var = 0 ;
1550  }
1551 
1552  // if 'v' is null, just set _var to null and exit.
1553  if (!v) {
1554  _var = 0;
1555  }
1556  else {
1557  // Jose Garcia
1558  // By getting a copy of this object to be assigned to _var
1559  // we let the owner of 'v' to deallocate it as necessary.
1560  _var = v->ptr_duplicate();
1561 
1562  // If 'v' has a name, use it as the name of the array. If it *is*
1563  // empty, then make sure to copy the array's name to the template
1564  // so that software which uses the template's name will still work.
1565  if (!v->name().empty())
1566  set_name(v->name());
1567  else
1568  _var->set_name(name());
1569 
1570  _var->set_parent(this); // Vector --> child
1571 
1572  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1573  << v->name() << " " << v->type_name() << ")" << endl);
1574  }
1575 }
1576 
1577 bool Vector::check_semantics(string & msg, bool)
1578 {
1579  return BaseType::check_semantics(msg);
1580 }
1581 
1590 void
1591 Vector::dump(ostream &strm) const
1592 {
1593  strm << DapIndent::LMarg << "Vector::dump - ("
1594  << (void *)this << ")" << endl ;
1595  DapIndent::Indent() ;
1596  BaseType::dump(strm) ;
1597  strm << DapIndent::LMarg << "# elements in vector: " << _length << endl ;
1598  if (_var) {
1599  strm << DapIndent::LMarg << "base type:" << endl ;
1600  DapIndent::Indent() ;
1601  _var->dump(strm) ;
1603  }
1604  else {
1605  strm << DapIndent::LMarg << "base type: not set" << endl ;
1606  }
1607  strm << DapIndent::LMarg << "vector contents:" << endl ;
1608  DapIndent::Indent() ;
1609  for (unsigned i = 0; i < _vec.size(); ++i) {
1610  if (_vec[i])
1611  _vec[i]->dump(strm) ;
1612  else
1613  strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl ;
1614  }
1616  strm << DapIndent::LMarg << "strings:" << endl ;
1617  DapIndent::Indent() ;
1618  for (unsigned i = 0; i < d_str.size(); i++) {
1619  strm << DapIndent::LMarg << d_str[i] << endl ;
1620  }
1622  if( _buf )
1623  {
1624  switch( _var->type() )
1625  {
1626  case dods_byte_c:
1627  {
1628  strm << DapIndent::LMarg << "_buf: " ;
1629  strm.write( _buf, _length ) ;
1630  strm << endl ;
1631  }
1632  break ;
1633  default:
1634  {
1635  strm << DapIndent::LMarg << "_buf: " << (void *)_buf << endl ;
1636  }
1637  break ;
1638  }
1639  }
1640  else
1641  {
1642  strm << DapIndent::LMarg << "_buf: EMPTY" << endl ;
1643  }
1645 }
1646 
1647 } // namespace libdap
1648 
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:790
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:444
virtual void put_int(int val)=0
bool is_cardinal_type() const
Definition: Vector.cc:111
static void UnIndent()
Definition: DapIndent.cc:49
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1068
uint8_t dods_byte
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1007
Part
Names the parts of multi-section constructor data types.
Definition: BaseType.h:98
#define not_used
Definition: config.h:850
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:217
virtual void put_str(const string &val)=0
void _duplicate(const Vector &v)
Definition: Vector.cc:61
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:78
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Vector.cc:1591
void clear_local_data()
Definition: Vector.cc:1039
virtual int length() const
Definition: Vector.cc:524
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:358
virtual void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
Definition: Vector.cc:1543
virtual unsigned int width()=0
Returns the size of the class instance data.
void delete_cardinal_data_buffer()
Definition: Vector.cc:192
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:326
virtual void * value()
Definition: Vector.cc:1521
void timeout_off()
Definition: DDS.cc:687
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition: Vector.cc:1173
Type
Identifies the data type.
Definition: BaseType.h:131
Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:238
uint16_t dods_uint16
#define DBG2(x)
Definition: debug.h:73
stack< BaseType * > btp_stack
Definition: BaseType.h:214
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Serialize a Vector.
Definition: Vector.cc:636
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:638
A class for software fault reporting.
Definition: InternalErr.h:64
virtual bool is_constructor_type()
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable...
Definition: BaseType.cc:356
string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:231
bool eval_selection(DDS &dds, const string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:383
virtual void get_str(string &val)=0
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Vector.cc:724
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:662
#define DBG(x)
Definition: debug.h:58
string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:252
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:407
virtual void set_send_p(bool state)
Definition: BaseType.cc:517
double dods_float64
static void Indent()
Definition: DapIndent.cc:43
virtual void dump(ostream &strm) const
dumps information about this object
Definition: BaseType.cc:186
uint32_t dods_uint32
virtual void reserve_value_capacity()
Definition: Vector.cc:1138
Vector & operator=(const Vector &rhs)
Definition: Vector.cc:303
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:483
unsigned int create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:159
void set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:206
virtual ~Vector()
Definition: Vector.cc:290
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer. Thrown if called for Structure, Sequence or Grid.
Definition: Vector.cc:848
virtual bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: Vector.cc:1577
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
string name() const
Returns the name of the class instance.
Definition: BaseType.cc:210
virtual void put_vector(char *val, int num, Vector &vec)=0
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:218
void timeout_on()
Definition: DDS.cc:679
Vector(const string &n, BaseType *v, const Type &t)
The Vector constructor.
Definition: Vector.cc:239
Evaluate a constraint expression.
static ostream & LMarg(ostream &strm)
Definition: DapIndent.cc:78
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:346
int16_t dods_int16
The basic data type for the DODS DAP types.
Definition: BaseType.h:190
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:53
virtual void set_name(const std::string &name)
Definition: Vector.cc:316
virtual unsigned int buf2val(void **val)
Definition: Vector.cc:935
virtual void get_int(int &val)=0
virtual void set_length(int l)
Definition: Vector.cc:535
virtual unsigned int width()
Returns the width of the data, in bytes.
Definition: Vector.cc:507
virtual bool set_value(dods_byte *val, int sz)
set the value of a byte array
Definition: Vector.cc:1272
virtual void intern_data(ConstraintEvaluator &eval, DDS &dds)
read data into a variable for later use
Definition: Vector.cc:570
void vec_resize(int l)
Definition: Vector.cc:548
virtual void get_vector(char **val, unsigned int &num, Vector &vec)=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:1036
int32_t dods_int32