libdap++  Updated for version 3.11.7
Vector.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // (c) COPYRIGHT URI/MIT 1995-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 // Implementation for class Vector. This class is the basis for all the
32 // vector-type classes in libdap's <Array, List>.
33 //
34 // 11/21/95 jhrg
35 
36 #include "config.h"
37 
38 #include <cstring>
39 
40 //#define DODS_DEBUG
41 
42 #include <algorithm>
43 
44 #include "Vector.h"
45 #include "escaping.h"
46 #include "util.h"
47 #include "debug.h"
48 #include "InternalErr.h"
49 #include <sstream>
50 
51 using std::cerr;
52 using std::endl;
53 
54 namespace libdap {
55 
56 void Vector::_duplicate(const Vector & v)
57 {
58  _length = v._length;
59 
60  // _var holds the type of the elements. That is, it holds a BaseType
61  // which acts as a template for the type of each element.
62  if (v._var) {
63  _var = v._var->ptr_duplicate(); // use ptr_duplicate()
64  _var->set_parent(this); // ptr_duplicate does not set d_parent.
65  }
66  else {
67  _var = 0;
68  }
69 
70  // _vec and _buf (further down) hold the values of the Vector. The field
71  // _vec is used when the Vector holds non-numeric data (including strings
72  // although it used to be that was not the case jhrg 2/10/05) while _buf
73  // holds numeric values.
74  if (v._vec.empty()) {
75  _vec = v._vec;
76  }
77  else {
78  // Failure to set the size will make the [] operator barf on the LHS
79  // of the assignment inside the loop.
80  _vec.resize(_length);
81  for (int i = 0; i < _length; ++i) {
82  // There's no need to call set_parent() for each element; we
83  // maintain the back pointer using the _var member. These
84  // instances are used to hold _values_ only while the _var
85  // field holds the type of the elements.
86  _vec[i] = v._vec[i]->ptr_duplicate();
87  }
88  }
89 
90  // copy the strings. This copies the values.
91  d_str = v.d_str;
92 
93  // copy numeric values if there are any.
94  _buf = 0; // init to null
95  if (v._buf) // only copy if data present
96  val2buf(v._buf); // store v's value in this's _BUF.
97 
98  _capacity = v._capacity;
99 }
100 
106 {
107  // Not cardinal if no _var at all!
108  if (!_var) {
109  return false;
110  }
111 
112  switch (_var->type()) {
113  case dods_byte_c:
114  case dods_int16_c:
115  case dods_uint16_c:
116  case dods_int32_c:
117  case dods_uint32_c:
118  case dods_float32_c:
119  case dods_float64_c: {
120  return true;
121  break;
122  }
123 
124  // These must be handled differently.
125  case dods_str_c:
126  case dods_url_c:
127  case dods_array_c:
128  case dods_structure_c:
129  case dods_sequence_c:
130  case dods_grid_c:
131  return false;
132  break;
133 
134  default:
135  cerr << "Vector::var: Unrecognized type" << endl;
136  return false;
137  } // switch
138 }
139 
152 unsigned int Vector::create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
153 {
154  // Make sure we HAVE a _var, or we cannot continue.
155  if (!_var) {
156  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
157  }
158 
159  // Make sure we only do this for the correct data types.
160  if (!is_cardinal_type()) {
161  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
162  }
163 
165 
166  // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
167  unsigned int bytesPerElt = _var->width();
168  unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
169  _buf = new char[bytesNeeded];
170  if (!_buf) {
171  ostringstream oss;
172  oss << "create_cardinal_data_buffer_for_type: new char[] failed to allocate " << bytesNeeded << " bytes! Out of memory or too large a buffer required!";
173  throw InternalErr(__FILE__, __LINE__, oss.str());
174  }
175  _capacity = numEltsOfType;
176  return bytesNeeded;
177 }
178 
181 {
182  if (_buf) {
183  delete[] _buf;
184  _buf = 0;
185  _capacity = 0;
186  }
187 }
188 
192 template<class CardType>
193 void Vector::set_cardinal_values_internal(const CardType* fromArray, int numElts)
194 {
195  if (numElts < 0) {
196  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
197  }
198  if (!fromArray) {
199  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
200  }
201  set_length(numElts);
203  memcpy(_buf, fromArray, numElts * sizeof(CardType));
204  set_read_p(true);
205 }
206 
223 Vector::Vector(const string & n, BaseType * v, const Type & t) :
224  BaseType(n, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
225 {
226  if (v)
227  add_var(v);
228 
229  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
230  if (_var)
231  _var->set_parent(this);
232 }
233 
253 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t) :
254  BaseType(n, d, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
255 {
256  if (v)
257  add_var(v);
258 
259  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
260  if (_var)
261  _var->set_parent(this);
262 }
263 
265 Vector::Vector(const Vector & rhs) :
266  BaseType(rhs)
267 {
268  DBG2(cerr << "Entering Vector const ctor for object: " << this <<
269  endl); DBG2(cerr << "RHS: " << &rhs << endl);
270 
271  _duplicate(rhs);
272 }
273 
275 {
276  DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
277 
278  delete _var;
279  _var = 0;
280 
281  // Clears all buffers
283 
284  DBG2(cerr << "Exiting ~Vector" << endl);
285 }
286 
288 {
289  if (this == &rhs)
290  return *this;
291 
292  dynamic_cast<BaseType &> (*this) = rhs;
293 
294  _duplicate(rhs);
295 
296  return *this;
297 }
298 
299 void Vector::set_name(const std::string& name)
300 {
301  BaseType::set_name(name);
302  // We need to set the template variable name as well since
303  // this is what gets output in the dds! Otherwise, there's a mismatch.
304  if (_var) {
305  _var->set_name(name);
306  }
307 }
308 
309 int Vector::element_count(bool leaves)
310 {
311  if (!leaves)
312  return 1;
313  else
314  // var() only works for simple types!
315  return var(0)->element_count(leaves);
316 }
317 
318 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
319 // from BaseType's version in that they set both the Vector object's copy of
320 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
321 // is a scalar, but does matter when it is an aggregate.
322 
329 void Vector::set_send_p(bool state)
330 {
331  _var->set_send_p(state);
332  BaseType::set_send_p(state);
333 }
334 
341 void Vector::set_read_p(bool state)
342 {
343  if (_var) {
344  _var->set_read_p(state);
345  }
346  BaseType::set_read_p(state);
347 }
348 
366 BaseType *Vector::var(const string & n, bool exact, btp_stack * s)
367 {
368  string name = www2id(n);
369  DBG(cerr << "Vector::var: Looking for " << n << endl);
370 
371  // Make sure to check for the case where name is the default (the empty
372  // string). 9/1/98 jhrg
373  if (_var->is_constructor_type()) {
374  if (name == "" || _var->name() == name) {
375  if (s)
376  s->push(this);
377  return _var;
378  }
379  else {
380  BaseType * result = _var->var(name, exact, s);
381  if (result && s)
382  s->push(this);
383  return result;
384  }
385  }
386  else {
387  return _var; // I don't see why this isn't return 0 *** jhrg 10/9/08
388  }
389 }
390 
401 BaseType *Vector::var(const string & n, btp_stack & s)
402 {
403  string name = www2id(n);
404 
405  if (_var->is_constructor_type())
406  return _var->var(name, s);
407  else {
408  s.push((BaseType *) this);
409  return _var;
410  }
411 }
412 
413 // Return a pointer the the BaseType object for element I. If the Vector is
414 // of a cardinal type, store the ith element's value in the BaseType
415 // object. If it is a Vector of a non-cardinal type, then this mfunc returns
416 // _vec[i].
417 //
418 // NB: I defaults to zero.
419 //
420 // Returns: A BaseType pointer to the ith element of the Vector.
421 
433 BaseType *Vector::var(unsigned int i)
434 {
435 
436  switch (_var->type()) {
437  case dods_byte_c:
438  case dods_int16_c:
439  case dods_uint16_c:
440  case dods_int32_c:
441  case dods_uint32_c:
442  case dods_float32_c:
443  case dods_float64_c: {
444  // Transfer the ith value to the BaseType *_var; There are more
445  // efficient ways to get a whole array using buf2val() but this is
446  // an OK way to get a single value or several non-contiguous values.
447  unsigned int sz = _var->width();
448  _var->val2buf((char *) _buf + (i * sz));
449  return _var;
450  break;
451  }
452 
453  case dods_str_c:
454  case dods_url_c:
455  _var->val2buf(&d_str[i]);
456  return _var;
457  break;
458 
459  case dods_array_c:
460  case dods_structure_c:
461  case dods_sequence_c:
462  case dods_grid_c:
463  return _vec[i];
464  break;
465 
466  default:
467  cerr << "Vector::var: Unrecognized type" << endl;
468  }
469 
470  return 0;
471 }
472 
473 // Return: The number of bytes required to store the vector `in a C
474 // program'. For an array of cardinal types this is the same as the storage
475 // used by _BUF. For anything else, it is the product of length() and the
476 // element width(). It turns out that both values can be computed the same
477 // way.
478 //
479 // Returns: The number of bytes used to store the vector.
480 
486 unsigned int Vector::width()
487 {
488  // Jose Garcia
489  if (!_var) {
490  throw InternalErr(__FILE__, __LINE__, "Cannot get width since *this* object is not holding data.");
491  }
492 
493  return length() * _var->width();
494 }
495 
496 // Returns: the number of elements in the vector.
497 
502 int Vector::length() const
503 {
504  return _length;
505 }
506 
507 // set the number of elements in the vector.
508 //
509 // Returns: void
510 
514 {
515  _length = l;
516 }
517 
518 // \e l is the number of elements the vector can hold (e.g., if l == 20, then
519 // the vector can hold elements 0, .., 19).
520 
527 {
528  _vec.resize((l > 0) ? l : 0, 0); // Fill with NULLs
529  _capacity = l; // capacity in terms of number of elements.
530 }
531 
548 {
549  DBG(cerr << "Vector::intern_data: " << name() << endl);
550  if (!read_p())
551  read(); // read() throws Error and InternalErr
552 
553  // length() is not capacity; it must be set explicitly in read().
554  int num = length();
555 
556  switch (_var->type()) {
557  case dods_byte_c:
558  case dods_int16_c:
559  case dods_uint16_c:
560  case dods_int32_c:
561  case dods_uint32_c:
562  case dods_float32_c:
563  case dods_float64_c:
564  // For these cases, read() puts the data into _buf, which is what we
565  // need to do 'stuff' with the data.
566  break;
567 
568  case dods_str_c:
569  case dods_url_c:
570  // For these cases, read() will put the data into d_str[], which is
571  // what the transformation classes need.
572  break;
573 
574  case dods_array_c:
575  // I think this is an error since there can never be an Array of
576  // Array.
577  throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
578  break;
579 
580  case dods_structure_c:
581  case dods_sequence_c:
582  case dods_grid_c:
583  DBG(cerr << "Vector::intern_data: found ctor" << endl);
584  // For these cases, we need to call read() for each of the 'num'
585  // elements in the '_vec[]' array of BaseType object pointers.
586  if (_vec.capacity() == 0)
587  throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
588 
589  for (int i = 0; i < num; ++i)
590  _vec[i]->intern_data(eval, dds);
591 
592  break;
593 
594  default:
595  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
596  break;
597  }
598 }
599 
611 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
612 {
613  int i = 0;// TODO move closer to use
614 
615  dds.timeout_on();
616 
617  if (!read_p())
618  read(); // read() throws Error and InternalErr
619 
620 #if EVAL
621  if (ce_eval && !eval.eval_selection(dds, dataset()))
622  return true;
623 #endif
624 
625  dds.timeout_off();
626 
627  // length() is not capacity; it must be set explicitly in read().
628  int num = length();
629 
630  switch (_var->type()) {
631  case dods_byte_c:
632  m.put_vector(_buf, num, *this);
633  break;
634  case dods_int16_c:
635  case dods_uint16_c:
636  case dods_int32_c:
637  case dods_uint32_c:
638  case dods_float32_c:
639  case dods_float64_c:
640  m.put_vector(_buf, num, _var->width(), *this);
641  break;
642 
643  case dods_str_c:
644  case dods_url_c:
645  if (d_str.capacity() == 0)
646  throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
647 
648  m.put_int(num);
649 
650  for (i = 0; i < num; ++i)
651  m.put_str(d_str[i]);
652 
653  break;
654 
655  case dods_array_c:
656  case dods_structure_c:
657  case dods_sequence_c:
658  case dods_grid_c:
659  //Jose Garcia
660  // Not setting the capacity of _vec is an internal error.
661  if (_vec.capacity() == 0)
662  throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
663 
664  m.put_int(num);
665 
666  for (i = 0; i < num; ++i)
667  _vec[i]->serialize(eval, dds, m, false);
668 
669  break;
670 
671  default:
672  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
673  break;
674  }
675 
676  return true;
677 }
678 
679 // Read an object from the network and internalize it. For a Vector this is
680 // handled differently for a `cardinal' type. Vectors of Cardinals are
681 // stored using the `C' representations because these objects often are used
682 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
683 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
684 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
685 // Grid are vectors of the libdap Structure, ... classes).
686 //
687 // The boolean parameter REUSE determines whether internal storage is reused
688 // or not. If true, the _buf member is assumed to be large enough to hold the
689 // incoming cardinal data and is *not* reallocated. If false, new storage is
690 // allocated. If the internal buffer has not yet been allocated, then this
691 // parameter has no effect (i.e., storage is allocated). This parameter
692 // effects storage for cardinal data only.
693 //
694 // Returns: True is successful, false otherwise.
695 
696 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
697 {
698  unsigned int num;
699  unsigned i = 0;
700 
701  switch (_var->type()) {
702  case dods_byte_c:
703  case dods_int16_c:
704  case dods_uint16_c:
705  case dods_int32_c:
706  case dods_uint32_c:
707  case dods_float32_c:
708  case dods_float64_c:
709  if (_buf && !reuse) {
711  }
712 
713  um.get_int((int &) num);
714 
715  DBG(cerr << "Vector::deserialize: num = " << num << endl);
716  DBG(cerr << "Vector::deserialize: length = " << length() << endl);
717 
718  if (length() == -1)
719  set_length(num);
720 
721  if (num != (unsigned int) length())
722  throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes.");
723 
724  if (!_buf) {
725  // Make _buf be large enough for length() elements of _var->type()
727  DBG(cerr << "Vector::deserialize: allocating "
728  << width() << " bytes for an array of "
729  << length() << " " << _var->type_name() << endl);
730  }
731 
732  if (_var->type() == dods_byte_c)
733  um.get_vector((char **) &_buf, num, *this);
734  else
735  um.get_vector((char **) &_buf, num, _var->width(), *this);
736 
737  DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
738 
739  break;
740 
741  case dods_str_c:
742  case dods_url_c:
743  um.get_int((int &) num);
744 
745  if (length() == -1)
746  set_length(num);
747 
748  if (num != (unsigned int) length())
749  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
750 
751  d_str.resize((num > 0) ? num : 0); // Fill with NULLs
752  _capacity = num; // capacity is number of strings we can fit.
753 
754  for (i = 0; i < num; ++i) {
755  string str;
756  um.get_str(str);
757  d_str[i] = str;
758 
759  }
760 
761  break;
762 
763  case dods_array_c:
764  case dods_structure_c:
765  case dods_sequence_c:
766  case dods_grid_c:
767  um.get_int((int &) num);
768 
769  if (length() == -1)
770  set_length(num);
771 
772  if (num != (unsigned int) length())
773  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
774 
775  vec_resize(num);
776 
777  for (i = 0; i < num; ++i) {
778  _vec[i] = _var->ptr_duplicate();
779  _vec[i]->deserialize(um, dds);
780  }
781 
782  break;
783 
784  default:
785  throw InternalErr(__FILE__, __LINE__, "Unknown type!");
786  break;
787  }
788 
789  return false;
790 }
791 
819 unsigned int Vector::val2buf(void *val, bool reuse)
820 {
821  // Jose Garcia
822 
823  // I *think* this method has been mainly designed to be use by read which
824  // is implemented in the surrogate library. Passing NULL as a pointer to
825  // this method will be an error of the creator of the surrogate library.
826  // Even though I recognize the fact that some methods inside libdap++ can
827  // call val2buf, I think by now no coding bugs such as misusing val2buf
828  // will be in libdap++, so it will be an internal error from the
829  // surrogate library.
830  if (!val)
831  throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
832 
833  switch (_var->type()) {
834  case dods_byte_c:
835  case dods_int16_c:
836  case dods_uint16_c:
837  case dods_int32_c:
838  case dods_uint32_c:
839  case dods_float32_c:
840  case dods_float64_c: {
841  // width() returns the size given the constraint
842  unsigned int array_wid = width();
843  if (_buf && !reuse) {
845  }
846 
847  if (!_buf) { // First time or no reuse (free'd above)
849  }
850 
851  memcpy(_buf, val, array_wid);
852  break;
853  }
854 
855  case dods_str_c:
856  case dods_url_c: {
857  // Assume val points to an array of C++ string objects. Copy
858  // them into the vector<string> field of this object.
859  d_str.resize(_length);
860  _capacity = _length;
861  for (int i = 0; i < _length; ++i)
862  d_str[i] = *(static_cast<string *> (val) + i);
863 
864  break;
865  }
866 
867  default:
868  throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
869 
870  }
871 
872  return width();
873 }
874 
905 unsigned int Vector::buf2val(void **val)
906 {
907  // Jose Garcia
908  // The same comment in Vector::val2buf applies here!
909  if (!val)
910  throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
911 
912  unsigned int wid = static_cast<unsigned int> (width());
913  // This is the width computed using length(). The
914  // length() property is changed when a projection
915  // constraint is applied. Thus this is the number of
916  // bytes in the buffer given the current constraint.
917 
918  switch (_var->type()) {
919  case dods_byte_c:
920  case dods_int16_c:
921  case dods_uint16_c:
922  case dods_int32_c:
923  case dods_uint32_c:
924  case dods_float32_c:
925  case dods_float64_c:
926  if (!*val) {
927  *val = new char[wid];
928  }
929  // avoid bus error if _buf is null and this is called improperly.
930  if (!_buf) {
931  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when _buf was null!");
932  }
933 
934  (void) memcpy(*val, _buf, wid);
935 
936  break;
937 
938  case dods_str_c:
939  case dods_url_c: {
940  if (!*val)
941  *val = new string[_length];
942 
943  for (int i = 0; i < _length; ++i)
944  *(static_cast<string *> (*val) + i) = d_str[i];
945 
946  break;
947  }
948 
949  default:
950  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
951  return 0;
952  }
953 
954  return wid;
955 }
956 
977 void Vector::set_vec(unsigned int i, BaseType * val)
978 {
979  // Jose Garcia
980  // This is a public method which allows users to set the elements
981  // of *this* vector. Passing an invalid index, a NULL pointer or
982  // mismatching the vector type are internal errors.
983  if (i >= static_cast<unsigned int> (_length))
984  throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
985  if (!val)
986  throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
987  if (val->type() != _var->type())
988  throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
989 
990  if (i >= _vec.capacity())
991  vec_resize(i + 10);
992 
993  _vec[i] = val->ptr_duplicate();
994 }
995 
1006 {
1007  if (_buf) {
1008  delete[] _buf;
1009  _buf = 0;
1010  }
1011 
1012  for (unsigned int i = 0; i < _vec.size(); ++i) {
1013  delete _vec[i];
1014  _vec[i] = 0;
1015  }
1016 
1017  // Force memory to be reclaimed.
1018  _vec.resize(0);
1019  d_str.resize(0);
1020 
1021  _capacity = 0;
1022  set_read_p(false);
1023 }
1024 
1032 unsigned int Vector::get_value_capacity() const
1033 {
1034  return _capacity;
1035 }
1036 
1046 void Vector::reserve_value_capacity(unsigned int numElements)
1047 {
1048  if (!_var) {
1049  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1050  }
1051  switch (_var->type()) {
1052  case dods_byte_c:
1053  case dods_int16_c:
1054  case dods_uint16_c:
1055  case dods_int32_c:
1056  case dods_uint32_c:
1057  case dods_float32_c:
1058  case dods_float64_c: {
1059  // Make _buf be the right size and set _capacity
1061  }
1062  break;
1063 
1064  case dods_str_c:
1065  case dods_url_c: {
1066  // Make sure the d_str has enough room for all the strings.
1067  // Technically not needed, but it will speed things up for large arrays.
1068  d_str.reserve(numElements);
1069  _capacity = numElements;
1070  }
1071  break;
1072 
1073  case dods_array_c:
1074  case dods_structure_c:
1075  case dods_sequence_c:
1076  case dods_grid_c: {
1077  // not clear anyone will go this path, but best to be complete.
1078  _vec.reserve(numElements);
1079  _capacity = numElements;
1080  }
1081  break;
1082 
1083  default: {
1084  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1085  }
1086  break;
1087 
1088  } // switch
1089 
1090 }
1091 
1098 {
1099  // Use the current length of the vector as the reserve amount.
1101 }
1102 
1131 unsigned int Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1132 {
1133  static const string funcName = "set_value_slice_from_row_major_vector:";
1134 
1135  // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1136  Vector& rowMajorData = const_cast<Vector&> (rowMajorDataC);
1137 
1138  bool typesMatch = rowMajorData.var() && _var && (rowMajorData.var()->type() == _var->type());
1139  if (!typesMatch) {
1140  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1141  }
1142 
1143  // Make sure the data exists
1144  if (!rowMajorData.read_p()) {
1145  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1146  }
1147 
1148  // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1149  if (rowMajorData.length() < 0) {
1150  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1151  }
1152 
1153  // The read-in capacity had better be at least the length (the amountt we will copy) or we'll memcpy into bad memory
1154  // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1155  if (rowMajorData.get_value_capacity() < static_cast<unsigned int> (rowMajorData.length())) {
1156  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1157  }
1158 
1159  // Make sure there's enough room in this Vector to store all the elements requested. Again,
1160  // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1161  if (_capacity < (startElement + rowMajorData.length())) {
1162  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1163  }
1164 
1165  // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1166  switch (_var->type()) {
1167  case dods_byte_c:
1168  case dods_int16_c:
1169  case dods_uint16_c:
1170  case dods_int32_c:
1171  case dods_uint32_c:
1172  case dods_float32_c:
1173  case dods_float64_c: {
1174  if (!_buf) {
1175  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1176  }
1177  if (!rowMajorData._buf) {
1178  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1179  }
1180  // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1181  int varWidth = _var->width();
1182  char* pFromBuf = rowMajorData._buf;
1183  int numBytesToCopy = rowMajorData.width();
1184  char* pIntoBuf = _buf + (startElement * varWidth);
1185  memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1186  }
1187  break;
1188 
1189  case dods_str_c:
1190  case dods_url_c: {
1191  // Strings need to be copied directly
1192  for (unsigned int i = 0; i < static_cast<unsigned int> (rowMajorData.length()); ++i) {
1193  d_str[startElement + i] = rowMajorData.d_str[i];
1194  }
1195  }
1196  break;
1197 
1198  case dods_array_c:
1199  case dods_structure_c:
1200  case dods_sequence_c:
1201  case dods_grid_c: {
1202  // Not sure that this function will be used for these type of nested objects, so I will throw here.
1203  // TODO impl and test this path if it's ever needed.
1204  throw InternalErr(__FILE__, __LINE__, funcName + "Unimplemented method for Vectors of type: dods_array_c, dods_structure_c, dods_sequence_c and dods_grid_c.");
1205  }
1206  break;
1207 
1208  default: {
1209  throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1210  }
1211  break;
1212 
1213  } // switch (_var->type())
1214 
1215  // This is how many elements we copied.
1216  return (unsigned int) rowMajorData.length();
1217 }
1218 
1220 
1221 bool Vector::set_value(dods_byte *val, int sz)
1222 {
1223  if (var()->type() == dods_byte_c && val) {
1224  set_cardinal_values_internal<dods_byte> (val, sz);
1225  return true;
1226  }
1227  else {
1228  return false;
1229  }
1230 }
1231 
1233 bool Vector::set_value(vector<dods_byte> &val, int sz)
1234 {
1235  return set_value(&val[0], sz);
1236 }
1237 
1239 bool Vector::set_value(dods_int16 *val, int sz)
1240 {
1241  if (var()->type() == dods_int16_c && val) {
1242  set_cardinal_values_internal<dods_int16> (val, sz);
1243  return true;
1244  }
1245  else {
1246  return false;
1247  }
1248 }
1249 
1251 bool Vector::set_value(vector<dods_int16> &val, int sz)
1252 {
1253  return set_value(&val[0], sz);
1254 }
1255 
1257 bool Vector::set_value(dods_int32 *val, int sz)
1258 {
1259  if (var()->type() == dods_int32_c && val) {
1260  set_cardinal_values_internal<dods_int32> (val, sz);
1261  return true;
1262  }
1263  else {
1264  return false;
1265  }
1266 }
1267 
1269 bool Vector::set_value(vector<dods_int32> &val, int sz)
1270 {
1271  return set_value(&val[0], sz);
1272 }
1273 
1275 bool Vector::set_value(dods_uint16 *val, int sz)
1276 {
1277  if (var()->type() == dods_uint16_c && val) {
1278  set_cardinal_values_internal<dods_uint16> (val, sz);
1279  return true;
1280  }
1281  else {
1282  return false;
1283  }
1284 }
1285 
1287 bool Vector::set_value(vector<dods_uint16> &val, int sz)
1288 {
1289  return set_value(&val[0], sz);
1290 }
1291 
1293 bool Vector::set_value(dods_uint32 *val, int sz)
1294 {
1295  if (var()->type() == dods_uint32_c && val) {
1296  set_cardinal_values_internal<dods_uint32> (val, sz);
1297  return true;
1298  }
1299  else {
1300  return false;
1301  }
1302 }
1303 
1305 bool Vector::set_value(vector<dods_uint32> &val, int sz)
1306 {
1307  return set_value(&val[0], sz);
1308 }
1309 
1312 {
1313  if (var()->type() == dods_float32_c && val) {
1314  set_cardinal_values_internal<dods_float32> (val, sz);
1315  return true;
1316  }
1317  else {
1318  return false;
1319  }
1320 }
1321 
1323 bool Vector::set_value(vector<dods_float32> &val, int sz)
1324 {
1325  return set_value(&val[0], sz);
1326 }
1327 
1330 {
1331  if (var()->type() == dods_float64_c && val) {
1332  set_cardinal_values_internal<dods_float64> (val, sz);
1333  return true;
1334  }
1335  else {
1336  return false;
1337  }
1338 }
1339 
1341 bool Vector::set_value(vector<dods_float64> &val, int sz)
1342 {
1343  return set_value(&val[0], sz);
1344 }
1345 
1347 bool Vector::set_value(string *val, int sz)
1348 {
1349  if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1350  d_str.resize(sz);
1351  _capacity = sz;
1352  for (register int t = 0; t < sz; t++) {
1353  d_str[t] = val[t];
1354  }
1355  set_length(sz);
1356  set_read_p(true);
1357  return true;
1358  }
1359  else {
1360  return false;
1361  }
1362 }
1363 
1365 bool Vector::set_value(vector<string> &val, int sz)
1366 {
1367  if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1368  d_str.resize(sz);
1369  _capacity = sz;
1370  for (register int t = 0; t < sz; t++) {
1371  d_str[t] = val[t];
1372  }
1373  set_length(sz);
1374  set_read_p(true);
1375  return true;
1376  }
1377  else {
1378  return false;
1379  }
1380 }
1382 
1384 
1391 void Vector::value(dods_byte *b) const
1392 {
1393  if (b && _var->type() == dods_byte_c) {
1394  memcpy(b, _buf, length() * sizeof(dods_byte));
1395  }
1396 }
1397 
1400 {
1401  if (b && _var->type() == dods_uint16_c) {
1402  memcpy(b, _buf, length() * sizeof(dods_uint16));
1403  }
1404 }
1405 
1408 {
1409  if (b && _var->type() == dods_int16_c) {
1410  memcpy(b, _buf, length() * sizeof(dods_int16));
1411  }
1412 }
1413 
1416 {
1417  if (b && _var->type() == dods_uint32_c) {
1418  memcpy(b, _buf, length() * sizeof(dods_uint32));
1419  }
1420 }
1421 
1424 {
1425  if (b && _var->type() == dods_int32_c) {
1426  memcpy(b, _buf, length() * sizeof(dods_int32));
1427  }
1428 }
1429 
1432 {
1433  if (b && _var->type() == dods_float32_c) {
1434  memcpy(b, _buf, length() * sizeof(dods_float32));
1435  }
1436 }
1437 
1440 {
1441  if (b && _var->type() == dods_float64_c) {
1442  memcpy(b, _buf, length() * sizeof(dods_float64));
1443  }
1444 }
1445 
1447 void Vector::value(vector<string> &b) const
1448 {
1449  if (_var->type() == dods_byte_c || _var->type() == dods_url_c)
1450  b = d_str;
1451 }
1452 
1456 {
1457  void *buffer = new char[width()];
1458 
1459  memcpy(buffer, _buf, width());
1460 
1461  return buffer;
1462 }
1464 
1478 {
1479  // Delete the current template variable
1480  if (_var) {
1481  delete _var;
1482  _var = 0;
1483  }
1484 
1485  // if 'v' is null, just set _var to null and exit.
1486  if (!v) {
1487  _var = 0;
1488  }
1489  else {
1490  // Jose Garcia
1491  // By getting a copy of this object to be assigned to _var
1492  // we let the owner of 'v' to deallocate it as necessary.
1493  _var = v->ptr_duplicate();
1494 
1495  // If 'v' has a name, use it as the name of the array. If it *is*
1496  // empty, then make sure to copy the array's name to the template
1497  // so that software which uses the template's name will still work.
1498  if (!v->name().empty())
1499  set_name(v->name());
1500  else
1501  _var->set_name(name());
1502 
1503  _var->set_parent(this); // Vector --> child
1504 
1505  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1506  << v->name() << " " << v->type_name() << ")" << endl);
1507  }
1508 }
1509 
1511 {
1512  // Delete the current template variable
1513  if (_var) {
1514  delete _var;
1515  _var = 0;
1516  }
1517 
1518  // if 'v' is null, just set _var to null and exit.
1519  if (!v) {
1520  _var = 0;
1521  }
1522  else {
1523  _var = v;
1524 
1525  // If 'v' has a name, use it as the name of the array. If it *is*
1526  // empty, then make sure to copy the array's name to the template
1527  // so that software which uses the template's name will still work.
1528  if (!v->name().empty())
1529  set_name(v->name());
1530  else
1531  _var->set_name(name());
1532 
1533  _var->set_parent(this); // Vector --> child
1534 
1535  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1536  << v->name() << " " << v->type_name() << ")" << endl);
1537  }
1538 }
1539 
1540 bool Vector::check_semantics(string & msg, bool)
1541 {
1542  return BaseType::check_semantics(msg);
1543 }
1544 
1553 void Vector::dump(ostream &strm) const
1554 {
1555  strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
1557  BaseType::dump(strm);
1558  strm << DapIndent::LMarg << "# elements in vector: " << _length << endl;
1559  if (_var) {
1560  strm << DapIndent::LMarg << "base type:" << endl;
1562  _var->dump(strm);
1564  }
1565  else {
1566  strm << DapIndent::LMarg << "base type: not set" << endl;
1567  }
1568  strm << DapIndent::LMarg << "vector contents:" << endl;
1570  for (unsigned i = 0; i < _vec.size(); ++i) {
1571  if (_vec[i])
1572  _vec[i]->dump(strm);
1573  else
1574  strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
1575  }
1577  strm << DapIndent::LMarg << "strings:" << endl;
1579  for (unsigned i = 0; i < d_str.size(); i++) {
1580  strm << DapIndent::LMarg << d_str[i] << endl;
1581  }
1583  if (_buf) {
1584  switch (_var->type()) {
1585  case dods_byte_c: {
1586  strm << DapIndent::LMarg << "_buf: ";
1587  strm.write(_buf, _length);
1588  strm << endl;
1589  }
1590  break;
1591  default: {
1592  strm << DapIndent::LMarg << "_buf: " << (void *) _buf << endl;
1593  }
1594  break;
1595  }
1596  }
1597  else {
1598  strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
1599  }
1601 }
1602 
1603 } // namespace libdap
1604