libdap  Updated for version 3.19.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
Vector.cc
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 #include <cassert>
40 
41 //#define DODS_DEBUG 1
42 
43 #include <sstream>
44 #include <vector>
45 #include <algorithm>
46 #include <typeinfo>
47 
48 #include <stdint.h>
49 
50 #include "crc.h"
51 
52 #include "Vector.h"
53 #include "Marshaller.h"
54 #include "UnMarshaller.h"
55 
56 #include "D4StreamMarshaller.h"
57 #include "D4StreamUnMarshaller.h"
58 
59 #include "D4Enum.h"
60 
61 #include "Type.h"
62 #include "dods-datatypes.h"
63 #include "escaping.h"
64 #include "util.h"
65 #include "debug.h"
66 #include "InternalErr.h"
67 
68 #undef CLEAR_LOCAL_DATA
69 
70 using std::cerr;
71 using std::endl;
72 
73 namespace libdap {
74 
75 void Vector::m_duplicate(const Vector & v)
76 {
77  d_length = v.d_length;
78 
79  // _var holds the type of the elements. That is, it holds a BaseType
80  // which acts as a template for the type of each element.
81  if (v.d_proto) {
82  d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
83  d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
84  }
85  else {
86  d_proto = 0;
87  }
88 
89  // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
90  // d_compound_buf is used when the Vector holds non-numeric data (including strings
91  // although it used to be that was not the case jhrg 2/10/05) while d_buf
92  // holds numeric values.
93  if (v.d_compound_buf.empty()) {
94  d_compound_buf = v.d_compound_buf;
95  }
96  else {
97  // Failure to set the size will make the [] operator barf on the LHS
98  // of the assignment inside the loop.
99  d_compound_buf.resize(d_length);
100  for (int i = 0; i < d_length; ++i) {
101  // There's no need to call set_parent() for each element; we
102  // maintain the back pointer using the d_proto member. These
103  // instances are used to hold _values_ only while the d_proto
104  // field holds the type information for the elements.
105  d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
106  }
107  }
108 
109  // copy the strings. This copies the values.
110  d_str = v.d_str;
111 
112  // copy numeric values if there are any.
113  d_buf = 0; // init to null
114  if (v.d_buf) // only copy if data present
115  val2buf(v.d_buf); // store v's value in this's _BUF.
116 
117  d_capacity = v.d_capacity;
118 }
119 
125 {
126  // Not cardinal if no d_proto at all!
127  if (!d_proto) {
128  return false;
129  }
130 
131  switch (d_proto->type()) {
132  case dods_byte_c:
133  case dods_char_c:
134  case dods_int16_c:
135  case dods_uint16_c:
136  case dods_int32_c:
137  case dods_uint32_c:
138  case dods_float32_c:
139  case dods_float64_c:
140  // New cardinal types for DAP4
141  case dods_int8_c:
142  case dods_uint8_c:
143  case dods_int64_c:
144  case dods_uint64_c:
145 
146  case dods_enum_c:
147  return true;
148  break;
149 
150  // These must be handled differently.
151  case dods_str_c:
152  case dods_url_c:
153  case dods_opaque_c:
154 
155  case dods_array_c:
156 
157  case dods_structure_c:
158  case dods_sequence_c:
159  case dods_grid_c:
160  return false;
161  break;
162 
163  default:
164  assert("Vector::var: Unrecognized type");
165  return false;
166  }
167 }
168 
181 unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
182 {
183  // Make sure we HAVE a _var, or we cannot continue.
184  if (!d_proto) {
185  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
186  }
187 
188  // Make sure we only do this for the correct data types.
189  if (!m_is_cardinal_type()) {
190  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
191  }
192 
194 
195  // Handle this special case where this is an array that holds no values
196  if (numEltsOfType == 0)
197  return 0;
198 
199  // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
200  unsigned int bytesPerElt = d_proto->width();
201  unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
202  d_buf = new char[bytesNeeded];
203 
204  d_capacity = numEltsOfType;
205  return bytesNeeded;
206 }
207 
210 {
211  delete[] d_buf;
212  d_buf = 0;
213  d_capacity = 0;
214 }
215 
219 template<class CardType>
220 void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
221 {
222  if (numElts < 0) {
223  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
224  }
225  if (!fromArray) {
226  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
227  }
228  set_length(numElts);
230  memcpy(d_buf, fromArray, numElts * sizeof(CardType));
231  set_read_p(true);
232 }
233 
249 Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
250  BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
251 {
252  if (v)
253  add_var(v);
254 
255  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
256  if (d_proto)
257  d_proto->set_parent(this);
258 }
259 
278 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
279  BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
280 {
281  if (v)
282  add_var(v);
283 
284  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
285  if (d_proto)
286  d_proto->set_parent(this);
287 }
288 
290 Vector::Vector(const Vector & rhs) :
291  BaseType(rhs)
292 {
293  DBG2(cerr << "Entering Vector const ctor for object: " << this <<
294  endl); DBG2(cerr << "RHS: " << &rhs << endl);
295 
296  m_duplicate(rhs);
297 }
298 
299 Vector::~Vector()
300 {
301  DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
302 
303  delete d_proto;
304  d_proto = 0;
305 
306  // Clears all buffers
308 
309  DBG2(cerr << "Exiting ~Vector" << endl);
310 }
311 
312 Vector & Vector::operator=(const Vector & rhs)
313 {
314  if (this == &rhs)
315  return *this;
316 
317  dynamic_cast<BaseType &> (*this) = rhs;
318 
319  m_duplicate(rhs);
320 
321  return *this;
322 }
323 
324 void Vector::set_name(const std::string& name)
325 {
327  // We need to set the prototype name as well since
328  // this is what gets output in the dds! Otherwise, there's a mismatch.
329  if (d_proto) {
330  d_proto->set_name(name);
331  }
332 }
333 
334 int Vector::element_count(bool leaves)
335 {
336  if (!leaves)
337  return 1;
338  else
339  return d_proto->element_count(leaves);
340  // var() only works for simple types!
341  // jhrg 8/19/13 return var(0)->element_count(leaves);
342 }
343 
344 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
345 // from BaseType's version in that they set both the Vector object's copy of
346 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
347 // is a scalar, but does matter when it is an aggregate.
348 
355 void Vector::set_send_p(bool state)
356 {
357  if (d_proto) {
358  d_proto->set_send_p(state);
359 
360  // because some code may depend on the BaseType*s held in d_compound_buf
361  // behaving as if they are 'ordinary' DAP variables, make sure their send_p
362  // flag is set if they exist. Because space in the vector is allocated
363  // before values (BaseType*s) are added, check for nulls and limit the
364  // iteration to only those elements actually in the object including any
365  // constraints that may have been applied - these are values not declarations.
366  // jhrg 5/13/16
367  switch (d_proto->type()) {
368  case dods_structure_c:
369  case dods_sequence_c:
370  case dods_grid_c:
371  if (d_compound_buf.size() > 0) {
372  for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
373  if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
374  }
375  }
376  break;
377 
378  default:
379  break;
380  }
381  }
382 
383  BaseType::set_send_p(state);
384 }
385 
392 void Vector::set_read_p(bool state)
393 {
394  if (d_proto) {
395  d_proto->set_read_p(state);
396 
397  // See comment above.
398  switch (d_proto->type()) {
399  case dods_structure_c:
400  case dods_sequence_c:
401  case dods_grid_c:
402  if (d_compound_buf.size() > 0) {
403  for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
404  if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
405  }
406  }
407  break;
408 
409  default:
410  break;
411  }
412  }
413 
414  BaseType::set_read_p(state);
415 }
416 
434 BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
435 {
436  string name = www2id(n);
437  DBG2(cerr << "Vector::var: Looking for " << name << endl);
438 
439  if (name == "" || d_proto->name() == name) {
440  if (s)
441  s->push(this);
442  return d_proto;
443  }
444 
445  // If this is a Vector of constructor types, look for 'name' recursively.
446  // Make sure to check for the case where name is the default (the empty
447  // string). 9/1/98 jhrg
448  if (d_proto->is_constructor_type()) {
449  BaseType *result = d_proto->var(name, exact, s);
450  if (result && s)
451  s->push(this);
452  return result;
453  }
454 
455  return NULL;
456 }
457 
468 BaseType *Vector::var(const string & n, btp_stack & s)
469 {
470  string name = www2id(n);
471 
472  if (d_proto->is_constructor_type())
473  return d_proto->var(name, s);
474  else {
475  s.push((BaseType *) this);
476  return d_proto;
477  }
478 }
479 
491 BaseType *Vector::var(unsigned int i)
492 {
493 
494  switch (d_proto->type()) {
495  case dods_byte_c:
496  case dods_char_c:
497  case dods_int8_c:
498  case dods_uint8_c:
499  case dods_int16_c:
500  case dods_uint16_c:
501  case dods_int32_c:
502  case dods_uint32_c:
503  case dods_int64_c:
504  case dods_uint64_c:
505 
506  case dods_enum_c:
507 
508  case dods_float32_c:
509  case dods_float64_c:
510  // Transfer the ith value to the BaseType *d_proto
511  d_proto->val2buf(d_buf + (i * d_proto->width()));
512  return d_proto;
513  break;
514 
515  case dods_str_c:
516  case dods_url_c:
517  d_proto->val2buf(&d_str[i]);
518  return d_proto;
519  break;
520 
521  case dods_opaque_c:
522  case dods_array_c:
523  case dods_structure_c:
524  case dods_sequence_c:
525  case dods_grid_c:
526  return d_compound_buf[i];
527  break;
528 
529  default:
530  throw Error ("Vector::var: Unrecognized type");
531  break;
532  }
533 
534  return 0;
535 }
536 
543 unsigned int Vector::width(bool constrained) const
544 {
545  // Jose Garcia
546  assert(d_proto);
547 
548  return length() * d_proto->width(constrained);
549 }
550 
555 int Vector::length() const
556 {
557  return d_length;
558 }
559 
563 {
564  d_length = l;
565 }
566 
576 {
577  // I added this check, which alters the behavior of the method. jhrg 8/14/13
578  if (m_is_cardinal_type())
579  throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
580 
581  // Use resize() since other parts of the code use operator[]. Note that size() should
582  // be used when resize() is used. Using capacity() creates problems as noted in the
583  // comment in set_vec_nocopy(). jhrg 5/19/17
584  d_compound_buf.resize(l, 0); // Fill with NULLs
585  d_capacity = d_compound_buf.size(); // size in terms of number of elements.
586 }
587 
605 {
606  DBG(cerr << "Vector::intern_data: " << name() << endl);
607  if (!read_p())
608  read(); // read() throws Error and InternalErr
609 
610  // length() is not capacity; it must be set explicitly in read().
611  int num = length();
612 
613  switch (d_proto->type()) {
614  case dods_byte_c:
615  case dods_int16_c:
616  case dods_uint16_c:
617  case dods_int32_c:
618  case dods_uint32_c:
619  case dods_float32_c:
620  case dods_float64_c:
621  // For these cases, read() puts the data into d_buf,
622  // which is what we need.
623  break;
624 
625  case dods_str_c:
626  case dods_url_c:
627  // For these cases, read() will put the data into d_str[],
628  // which is also what we need.
629  break;
630 
631  case dods_array_c:
632  // This is an error since there can never be an Array of Array.
633  throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
634  break;
635 
636  case dods_structure_c:
637  case dods_sequence_c:
638  case dods_grid_c:
639  DBG(cerr << "Vector::intern_data: found ctor" << endl);
640  // For these cases, we need to call read() for each of the 'num'
641  // elements in the 'd_compound_buf[]' array of BaseType object pointers.
642  //
643  // I changed the test here from '... = 0' to '... < num' to accommodate
644  // the case where the array is zero-length.
645  if (d_compound_buf.capacity() < (unsigned)num)
646  throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
647 
648  for (int i = 0; i < num; ++i)
649  d_compound_buf[i]->intern_data(eval, dds);
650 
651  break;
652 
653  default:
654  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
655  break;
656  }
657 }
658 
670 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
671 {
672 #if 0
673  dds.timeout_on();
674 #endif
675  // Added to streamline zero-length arrays. Not needed for correct function,
676  // but explicitly handling this case here makes the code easier to follow.
677  // In libdap::Vector::val2buf() there is a test that will catch the zero-length
678  // case as well. We still need to call serialize since it will write size
679  // information that the client depends on. jhrg 2/17/16
680  if (length() == 0)
681  set_read_p(true);
682  else if (!read_p())
683  read(); // read() throws Error and InternalErr
684 
685  if (ce_eval && !eval.eval_selection(dds, dataset()))
686  return true;
687 #if 0
688  dds.timeout_off();
689 #endif
690  // length() is not capacity; it must be set explicitly in read().
691  int num = length();
692 
693  bool status = false;
694 
695  switch (d_proto->type()) {
696  case dods_byte_c:
697  m.put_vector(d_buf, num, *this);
698  status = true;
699  break;
700 
701  case dods_int16_c:
702  case dods_uint16_c:
703  case dods_int32_c:
704  case dods_uint32_c:
705  case dods_float32_c:
706  case dods_float64_c:
707  m.put_vector(d_buf, num, d_proto->width(), *this);
708  status = true;
709 
710  break;
711 
712  case dods_str_c:
713  case dods_url_c:
714  if (d_str.capacity() == 0)
715  throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
716 
717  m.put_int(num);
718 
719  for (int i = 0; i < num; ++i)
720  m.put_str(d_str[i]);
721 
722  status = true;
723  break;
724 
725  case dods_array_c:
726  case dods_structure_c:
727  case dods_sequence_c:
728  case dods_grid_c:
729  //Jose Garcia
730  // Not setting the capacity of d_compound_buf is an internal error.
731  if (d_compound_buf.capacity() == 0)
732  throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
733 
734  m.put_int(num);
735  status = true;
736  for (int i = 0; i < num && status; ++i)
737  status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
738 
739  break;
740 
741  default:
742  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
743  break;
744  }
745 
746 #ifdef CLEAR_LOCAL_DATA
748 #endif
749 
750  return status;
751 }
752 
753 // Read an object from the network and internalize it. For a Vector this is
754 // handled differently for a `cardinal' type. Vectors of Cardinals are
755 // stored using the `C' representations because these objects often are used
756 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
757 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
758 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
759 // Grid are vectors of the libdap Structure, ... classes).
760 //
761 // The boolean parameter REUSE determines whether internal storage is reused
762 // or not. If true, the _buf member is assumed to be large enough to hold the
763 // incoming cardinal data and is *not* reallocated. If false, new storage is
764 // allocated. If the internal buffer has not yet been allocated, then this
765 // parameter has no effect (i.e., storage is allocated). This parameter
766 // effects storage for cardinal data only.
767 //
768 // Returns: True is successful, false otherwise.
769 
770 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
771 {
772  unsigned int num;
773  unsigned i = 0;
774 
775  switch (d_proto->type()) {
776  case dods_byte_c:
777  case dods_int16_c:
778  case dods_uint16_c:
779  case dods_int32_c:
780  case dods_uint32_c:
781  case dods_float32_c:
782  case dods_float64_c:
783  um.get_int((int &) num);
784 
785  DBG(cerr << "Vector::deserialize: num = " << num << endl);
786  DBG(cerr << "Vector::deserialize: length = " << length() << endl);
787 
788  if (length() == -1)
789  set_length(num);
790 
791  if (num != (unsigned int) length())
792  throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
793 
794  if (!d_buf || !reuse) {
795  // Make d_buf be large enough for length() elements of _var->type()
796  // m_create...() deletes the old buffer.
798  DBG(cerr << "Vector::deserialize: allocating "
799  << width() << " bytes for an array of "
800  << length() << " " << d_proto->type_name() << endl);
801  }
802 
803  // Added to accommodate zero-length arrays.
804  // Note that the rest of the cases will just send the size without data
805  // but that these calls trigger error testing in the UnMarshaller code.
806  // jhrg 1/28/16
807  if (num == 0)
808  return true;
809 
810  if (d_proto->type() == dods_byte_c)
811  um.get_vector((char **) &d_buf, num, *this);
812  else
813  um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
814 
815  DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
816 
817  break;
818 
819  case dods_str_c:
820  case dods_url_c:
821  um.get_int((int &) num);
822 
823  if (length() == -1)
824  set_length(num);
825 
826  if (num != (unsigned int) length())
827  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
828 
829  d_str.resize((num > 0) ? num : 0); // Fill with NULLs
830  d_capacity = num; // capacity is number of strings we can fit.
831 
832  for (i = 0; i < num; ++i) {
833  string str;
834  um.get_str(str);
835  d_str[i] = str;
836 
837  }
838 
839  break;
840 
841  case dods_array_c:
842  // Added jhrg 5/18/17
843  // This replaces a comment that was simply 'TO DO'
844  throw InternalErr(__FILE__, __LINE__, "Array of array!");
845  break;
846 
847  case dods_structure_c:
848  case dods_sequence_c:
849  case dods_grid_c:
850  um.get_int((int &) num);
851 
852  if (length() == -1)
853  set_length(num);
854 
855  if (num != (unsigned int) length())
856  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
857 
858  vec_resize(num);
859 
860  for (i = 0; i < num; ++i) {
861  d_compound_buf[i] = d_proto->ptr_duplicate();
862  d_compound_buf[i]->deserialize(um, dds);
863  }
864 
865  break;
866 
867  default:
868  throw InternalErr(__FILE__, __LINE__, "Unknown type!");
869  break;
870  }
871 
872  return false;
873 }
874 
876 {
877  switch (d_proto->type()) {
878  case dods_byte_c:
879  case dods_char_c:
880  case dods_int8_c:
881  case dods_uint8_c:
882 
883  case dods_int16_c:
884  case dods_uint16_c:
885 
886  case dods_int32_c:
887  case dods_uint32_c:
888  case dods_float32_c:
889 
890  case dods_int64_c:
891  case dods_uint64_c:
892  case dods_float64_c:
893 
894  case dods_enum_c:
895  checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
896  break;
897 
898  case dods_str_c:
899  case dods_url_c:
900  for (int64_t i = 0, e = length(); i < e; ++i)
901  checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
902  break;
903 
904  case dods_opaque_c:
905  case dods_structure_c:
906  case dods_sequence_c:
907  d_proto->compute_checksum(checksum);
908  break;
909 
910  case dods_array_c: // No array of array
911  case dods_grid_c: // No grids in DAP4
912  default:
913  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
914  break;
915  }
916 }
917 
918 void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
919 {
920  if (!read_p())
921  read(); // read() throws Error and InternalErr
922 
923  switch (d_proto->type()) {
924  case dods_byte_c:
925  case dods_char_c:
926  case dods_int8_c:
927  case dods_uint8_c:
928  case dods_int16_c:
929  case dods_uint16_c:
930  case dods_int32_c:
931  case dods_uint32_c:
932  case dods_int64_c:
933  case dods_uint64_c:
934 
935  case dods_enum_c:
936 
937  case dods_float32_c:
938  case dods_float64_c:
939 
940  case dods_str_c:
941  case dods_url_c:
942 #if 0
943  compute_checksum(checksum);
944 #endif
945  break;
946 
947  case dods_opaque_c:
948  case dods_structure_c:
949  case dods_sequence_c:
950  // Modified the assert here from '... != 0' to '... >= length())
951  // to accommodate the case of a zero-length array. jhrg 1/28/16
952  assert(d_compound_buf.capacity() >= (unsigned)length());
953 
954  for (int i = 0, e = length(); i < e; ++i)
955  d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
956  break;
957 
958  case dods_array_c: // No Array of Array in DAP4 either...
959  case dods_grid_c:
960  default:
961  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
962  break;
963  }
964 }
965 
966 void
967 Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/)
968 {
969  if (!read_p())
970  read(); // read() throws Error and InternalErr
971 #if 0
972  if (filter && !eval.eval_selection(dmr, dataset()))
973  return true;
974 #endif
975  int64_t num = length(); // The constrained length in elements
976 
977  DBG(cerr << __func__ << ", num: " << num << endl);
978 
979  // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
980  if (num == 0)
981  return;
982 
983  switch (d_proto->type()) {
984  case dods_byte_c:
985  case dods_char_c:
986  case dods_int8_c:
987  case dods_uint8_c:
988  m.put_vector(d_buf, num);
989  break;
990 
991  case dods_int16_c:
992  case dods_uint16_c:
993  case dods_int32_c:
994  case dods_uint32_c:
995  case dods_int64_c:
996  case dods_uint64_c:
997  m.put_vector(d_buf, num, d_proto->width());
998  break;
999 
1000  case dods_enum_c:
1001  if (d_proto->width() == 1)
1002  m.put_vector(d_buf, num);
1003  else
1004  m.put_vector(d_buf, num, d_proto->width());
1005  break;
1006 
1007  case dods_float32_c:
1008  m.put_vector_float32(d_buf, num);
1009  break;
1010 
1011  case dods_float64_c:
1012  m.put_vector_float64(d_buf, num);
1013  break;
1014 
1015  case dods_str_c:
1016  case dods_url_c:
1017  assert((int64_t)d_str.capacity() >= num);
1018 
1019  for (int64_t i = 0; i < num; ++i)
1020  m.put_str(d_str[i]);
1021 
1022  break;
1023 
1024  case dods_array_c:
1025  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1026 
1027  case dods_opaque_c:
1028  case dods_structure_c:
1029  case dods_sequence_c:
1030  assert(d_compound_buf.capacity() >= 0);
1031 
1032  for (int64_t i = 0; i < num; ++i) {
1033  DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
1034  d_compound_buf[i]->serialize(m, dmr, filter);
1035  }
1036 
1037  break;
1038 
1039  case dods_grid_c:
1040  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1041 
1042  default:
1043  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1044  break;
1045  }
1046 
1047 #ifdef CLEAR_LOCAL_DATA
1048  clear_local_data();
1049 #endif
1050 }
1051 
1052 void
1054 {
1055  if (m_is_cardinal_type()) {
1056  if (d_buf)
1058  if (!d_buf)
1060  }
1061 
1062  DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1063 
1064  // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1065  if (length() == 0)
1066  return;
1067 
1068  switch (d_proto->type()) {
1069  case dods_byte_c:
1070  case dods_char_c:
1071  case dods_int8_c:
1072  case dods_uint8_c:
1073  um.get_vector((char *)d_buf, length());
1074  break;
1075 
1076  case dods_int16_c:
1077  case dods_uint16_c:
1078  case dods_int32_c:
1079  case dods_uint32_c:
1080  case dods_int64_c:
1081  case dods_uint64_c:
1082  um.get_vector((char *)d_buf, length(), d_proto->width());
1083  break;
1084 
1085  case dods_enum_c:
1086  if (d_proto->width() == 1)
1087  um.get_vector((char *)d_buf, length());
1088  else
1089  um.get_vector((char *)d_buf, length(), d_proto->width());
1090  break;
1091 
1092  case dods_float32_c:
1093  um.get_vector_float32((char *)d_buf, length());
1094  break;
1095 
1096  case dods_float64_c:
1097  um.get_vector_float64((char *)d_buf, length());
1098  break;
1099 
1100  case dods_str_c:
1101  case dods_url_c: {
1102  int64_t len = length();
1103  d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1104  d_capacity = len; // capacity is number of strings we can fit.
1105 
1106  for (int64_t i = 0; i < len; ++i) {
1107  um.get_str(d_str[i]);
1108  }
1109 
1110  break;
1111  }
1112 
1113  case dods_array_c:
1114  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1115 
1116  case dods_opaque_c:
1117  case dods_structure_c:
1118  case dods_sequence_c: {
1119  vec_resize(length());
1120 
1121  for (int64_t i = 0, end = length(); i < end; ++i) {
1122  d_compound_buf[i] = d_proto->ptr_duplicate();
1123  d_compound_buf[i]->deserialize(um, dmr);
1124  }
1125 
1126  break;
1127  }
1128 
1129  case dods_grid_c:
1130  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1131 
1132  default:
1133  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1134  break;
1135  }
1136 }
1137 
1165 unsigned int Vector::val2buf(void *val, bool reuse)
1166 {
1167  // Jose Garcia
1168 
1169  // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1170  if (!val && length() == 0)
1171  return 0;
1172 
1173  // I *think* this method has been mainly designed to be use by read which
1174  // is implemented in the surrogate library. Passing NULL as a pointer to
1175  // this method will be an error of the creator of the surrogate library.
1176  // Even though I recognize the fact that some methods inside libdap++ can
1177  // call val2buf, I think by now no coding bugs such as misusing val2buf
1178  // will be in libdap++, so it will be an internal error from the
1179  // surrogate library.
1180  if (!val)
1181  throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1182 
1183  switch (d_proto->type()) {
1184  case dods_byte_c:
1185  case dods_char_c:
1186  case dods_int8_c:
1187  case dods_uint8_c:
1188  case dods_int16_c:
1189  case dods_uint16_c:
1190  case dods_int32_c:
1191  case dods_uint32_c:
1192  case dods_int64_c:
1193  case dods_uint64_c:
1194 
1195  case dods_enum_c:
1196 
1197  case dods_float32_c:
1198  case dods_float64_c:
1199 #if 0
1200  if (d_buf && !reuse)
1202 #endif
1203  // First time or no reuse (free'd above)
1204  if (!d_buf || !reuse)
1206 
1207  // width(true) returns the size in bytes given the constraint
1208  memcpy(d_buf, val, width(true));
1209  break;
1210 
1211  case dods_str_c:
1212  case dods_url_c:
1213  // Assume val points to an array of C++ string objects. Copy
1214  // them into the vector<string> field of this object.
1215  // Note: d_length is the number of elements in the Vector
1216  d_str.resize(d_length);
1217  d_capacity = d_length;
1218  for (int i = 0; i < d_length; ++i)
1219  d_str[i] = *(static_cast<string *> (val) + i);
1220 
1221  break;
1222 
1223  default:
1224  throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1225 
1226  }
1227 
1228  return width(true);
1229 }
1230 
1261 unsigned int Vector::buf2val(void **val)
1262 {
1263  // Jose Garcia
1264  // The same comment in Vector::val2buf applies here!
1265  if (!val)
1266  throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1267 
1268  unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1269 
1270  // This is the width computed using length(). The
1271  // length() property is changed when a projection
1272  // constraint is applied. Thus this is the number of
1273  // bytes in the buffer given the current constraint.
1274 
1275  switch (d_proto->type()) {
1276  case dods_byte_c:
1277  case dods_char_c:
1278  case dods_int8_c:
1279  case dods_uint8_c:
1280  case dods_int16_c:
1281  case dods_uint16_c:
1282  case dods_int32_c:
1283  case dods_uint32_c:
1284  case dods_int64_c:
1285  case dods_uint64_c:
1286 
1287  case dods_enum_c:
1288 
1289  case dods_float32_c:
1290  case dods_float64_c:
1291  if (!d_buf)
1292  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1293  if (!*val)
1294  *val = new char[wid];
1295 
1296  memcpy(*val, d_buf, wid);
1297  return wid;
1298  break;
1299 
1300  case dods_str_c:
1301  case dods_url_c: {
1302  if (d_str.empty())
1303  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1304  if (!*val)
1305  *val = new string[d_length];
1306 
1307  for (int i = 0; i < d_length; ++i)
1308  *(static_cast<string *> (*val) + i) = d_str[i];
1309 
1310  return width();
1311  break;
1312  }
1313 
1314  default:
1315  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1316  }
1317 
1318  //return wid;
1319 }
1320 
1341 void Vector::set_vec(unsigned int i, BaseType * val)
1342 {
1344 }
1345 
1357 void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1358 {
1359  // Jose Garcia
1360  // This is a public method which allows users to set the elements
1361  // of *this* vector. Passing an invalid index, a NULL pointer or
1362  // mismatching the vector type are internal errors.
1363  if (i >= static_cast<unsigned int> (d_length))
1364  throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1365  if (!val)
1366  throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1367  if (val->type() != d_proto->type())
1368  throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1369 
1370  // This code originally used capacity() instead of size(), but that was an error.
1371  // Use capacity() when using reserve() and size() when using resize(). Mixing
1372  // capacity() with resize() leaves holes in the data, where (pointer) values are
1373  // filled with nulls during successive calls to resize(). The resize() heuristic
1374  // remembers previous calls on a given vector<> and allocates larger than requested
1375  // blocks of memory on successive calls, which has the strange affect of erasing
1376  // values already in the vector in the parts just added.
1377  // jhrg 5/18/17
1378  if (i >= d_compound_buf.size()) {
1379  vec_resize(d_compound_buf.size() + 100);
1380  }
1381 
1382  d_compound_buf[i] = val;
1383 }
1384 
1395 {
1396  if (d_buf) {
1397  delete[] d_buf;
1398  d_buf = 0;
1399  }
1400 
1401  for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1402  delete d_compound_buf[i];
1403  d_compound_buf[i] = 0;
1404  }
1405 
1406  // Force memory to be reclaimed.
1407  d_compound_buf.resize(0);
1408  d_str.resize(0);
1409 
1410  d_capacity = 0;
1411  set_read_p(false);
1412 }
1413 
1421 unsigned int Vector::get_value_capacity() const
1422 {
1423  return d_capacity;
1424 }
1425 
1435 void Vector::reserve_value_capacity(unsigned int numElements)
1436 {
1437  if (!d_proto) {
1438  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1439  }
1440  switch (d_proto->type()) {
1441  case dods_byte_c:
1442  case dods_char_c:
1443  case dods_int8_c:
1444  case dods_uint8_c:
1445  case dods_int16_c:
1446  case dods_uint16_c:
1447  case dods_int32_c:
1448  case dods_uint32_c:
1449  case dods_int64_c:
1450  case dods_uint64_c:
1451 
1452  case dods_enum_c:
1453 
1454  case dods_float32_c:
1455  case dods_float64_c:
1456  // Make _buf be the right size and set _capacity
1458  break;
1459 
1460  case dods_str_c:
1461  case dods_url_c:
1462  // Make sure the d_str has enough room for all the strings.
1463  // Technically not needed, but it will speed things up for large arrays.
1464  d_str.reserve(numElements);
1465  d_capacity = numElements;
1466  break;
1467 
1468  case dods_array_c:
1469  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1470  break;
1471 
1472  case dods_opaque_c:
1473  case dods_structure_c:
1474  case dods_sequence_c:
1475  case dods_grid_c:
1476  // not clear anyone will go this path, but best to be complete.
1477  d_compound_buf.reserve(numElements);
1478  d_capacity = numElements;
1479  break;
1480 
1481  default:
1482  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1483  break;
1484 
1485  } // switch
1486 
1487 }
1488 
1495 {
1496  // Use the current length of the vector as the reserve amount.
1498 }
1499 
1528 unsigned int
1529 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1530 {
1531  static const string funcName = "set_value_slice_from_row_major_vector:";
1532 
1533  // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1534  Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1535 
1536  bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1537  if (!typesMatch) {
1538  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1539  }
1540 
1541  // Make sure the data exists
1542  if (!rowMajorData.read_p()) {
1543  throw InternalErr(__FILE__, __LINE__,
1544  funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1545  }
1546 
1547  // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1548  if (rowMajorData.length() < 0) {
1549  throw InternalErr(__FILE__, __LINE__,
1550  funcName
1551  + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1552  }
1553 
1554  // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1555  // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1556  if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1557  throw InternalErr(__FILE__, __LINE__,
1558  funcName
1559  + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1560  }
1561 
1562  // Make sure there's enough room in this Vector to store all the elements requested. Again,
1563  // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1564  if (d_capacity < (startElement + rowMajorData.length())) {
1565  throw InternalErr(__FILE__, __LINE__,
1566  funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1567  }
1568 
1569  // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1570  switch (d_proto->type()) {
1571  case dods_int8_c:
1572  case dods_uint8_c:
1573  case dods_byte_c:
1574  case dods_char_c:
1575  case dods_int16_c:
1576  case dods_uint16_c:
1577  case dods_int32_c:
1578  case dods_uint32_c:
1579  case dods_int64_c:
1580  case dods_uint64_c:
1581 
1582  case dods_enum_c:
1583 
1584  case dods_float32_c:
1585  case dods_float64_c: {
1586  if (!d_buf) {
1587  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1588  }
1589  if (!rowMajorData.d_buf) {
1590  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1591  }
1592  // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1593  int varWidth = d_proto->width();
1594  char* pFromBuf = rowMajorData.d_buf;
1595  int numBytesToCopy = rowMajorData.width(true);
1596  char* pIntoBuf = d_buf + (startElement * varWidth);
1597  memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1598  break;
1599  }
1600 
1601  case dods_str_c:
1602  case dods_url_c:
1603  // Strings need to be copied directly
1604  for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1605  d_str[startElement + i] = rowMajorData.d_str[i];
1606  }
1607  break;
1608 
1609  case dods_array_c:
1610  case dods_opaque_c:
1611  case dods_structure_c:
1612  case dods_sequence_c:
1613  case dods_grid_c:
1614  // Not sure that this function will be used for these type of nested objects, so I will throw here.
1615  throw InternalErr(__FILE__, __LINE__,
1616  funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1617  break;
1618 
1619  default:
1620  throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1621  break;
1622 
1623  } // switch (_var->type())
1624 
1625  // This is how many elements we copied.
1626  return (unsigned int) rowMajorData.length();
1627 }
1628 
1637 template <typename T>
1638 static bool types_match(Type t, T *cpp_var)
1639 {
1640  switch (t) {
1641  case dods_byte_c:
1642  case dods_char_c:
1643  case dods_uint8_c:
1644  return typeid(cpp_var) == typeid(dods_byte*);
1645 
1646  case dods_int8_c:
1647  return typeid(cpp_var) == typeid(dods_int8*);
1648  case dods_int16_c:
1649  return typeid(cpp_var) == typeid(dods_int16*);
1650  case dods_uint16_c:
1651  return typeid(cpp_var) == typeid(dods_uint16*);
1652  case dods_int32_c:
1653  return typeid(cpp_var) == typeid(dods_int32*);
1654  case dods_uint32_c:
1655  return typeid(cpp_var) == typeid(dods_uint32*);
1656  case dods_int64_c:
1657  return typeid(cpp_var) == typeid(dods_int64*);
1658  case dods_uint64_c:
1659  return typeid(cpp_var) == typeid(dods_uint64*);
1660 
1661  case dods_float32_c:
1662  return typeid(cpp_var) == typeid(dods_float32*);
1663  case dods_float64_c:
1664  return typeid(cpp_var) == typeid(dods_float64*);
1665 
1666  case dods_null_c:
1667  case dods_enum_c:
1668  case dods_str_c:
1669  case dods_url_c:
1670  case dods_opaque_c:
1671  case dods_array_c:
1672  case dods_structure_c:
1673  case dods_sequence_c:
1674  case dods_group_c:
1675  default:
1676  return false;
1677  }
1678 }
1679 
1681 
1683 template <typename T>
1684 bool Vector::set_value_worker(T *v, int sz)
1685 {
1686  if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1687  return false;
1688 
1690  return true;
1691 }
1692 
1693 bool Vector::set_value(dods_byte *val, int sz)
1694 {
1695  return set_value_worker(val, sz);
1696 }
1697 bool Vector::set_value(dods_int8 *val, int sz)
1698 {
1699  return set_value_worker(val, sz);
1700 }
1701 bool Vector::set_value(dods_int16 *val, int sz)
1702 {
1703  return set_value_worker(val, sz);
1704 }
1705 bool Vector::set_value(dods_uint16 *val, int sz)
1706 {
1707  return set_value_worker(val, sz);
1708 }
1709 bool Vector::set_value(dods_int32 *val, int sz)
1710 {
1711  return set_value_worker(val, sz);
1712 }
1713 bool Vector::set_value(dods_uint32 *val, int sz)
1714 {
1715  return set_value_worker(val, sz);
1716 }
1717 bool Vector::set_value(dods_int64 *val, int sz)
1718 {
1719  return set_value_worker(val, sz);
1720 }
1721 bool Vector::set_value(dods_uint64 *val, int sz)
1722 {
1723  return set_value_worker(val, sz);
1724 }
1725 bool Vector::set_value(dods_float32 *val, int sz)
1726 {
1727  return set_value_worker(val, sz);
1728 }
1729 bool Vector::set_value(dods_float64 *val, int sz)
1730 {
1731  return set_value_worker(val, sz);
1732 }
1733 
1735 bool Vector::set_value(string *val, int sz)
1736 {
1737  if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1738  d_str.resize(sz);
1739  d_capacity = sz;
1740  for (register int t = 0; t < sz; t++) {
1741  d_str[t] = val[t];
1742  }
1743  set_length(sz);
1744  set_read_p(true);
1745  return true;
1746  }
1747  else {
1748  return false;
1749  }
1750 }
1751 
1752 template<typename T>
1753 bool Vector::set_value_worker(vector<T> &v, int sz)
1754 {
1755  return set_value(&v[0], sz);
1756 }
1757 
1758 bool Vector::set_value(vector<dods_byte> &val, int sz)
1759 {
1760  return set_value_worker(val, sz);
1761 }
1762 bool Vector::set_value(vector<dods_int8> &val, int sz)
1763 {
1764  return set_value_worker(val, sz);
1765 }
1766 bool Vector::set_value(vector<dods_int16> &val, int sz)
1767 {
1768  return set_value_worker(val, sz);
1769 }
1770 bool Vector::set_value(vector<dods_uint16> &val, int sz)
1771 {
1772  return set_value_worker(val, sz);
1773 }
1774 bool Vector::set_value(vector<dods_int32> &val, int sz)
1775 {
1776  return set_value_worker(val, sz);
1777 }
1778 bool Vector::set_value(vector<dods_uint32> &val, int sz)
1779 {
1780  return set_value_worker(val, sz);
1781 }
1782 bool Vector::set_value(vector<dods_int64> &val, int sz)
1783 {
1784  return set_value_worker(val, sz);
1785 }
1786 bool Vector::set_value(vector<dods_uint64> &val, int sz)
1787 {
1788  return set_value_worker(val, sz);
1789 }
1790 bool Vector::set_value(vector<dods_float32> &val, int sz)
1791 {
1792  return set_value_worker(val, sz);
1793 }
1794 bool Vector::set_value(vector<dods_float64> &val, int sz)
1795 {
1796  return set_value_worker(val, sz);
1797 }
1798 
1799 
1801 bool Vector::set_value(vector<string> &val, int sz)
1802 {
1803  if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1804  d_str.resize(sz);
1805  d_capacity = sz;
1806  for (register int t = 0; t < sz; t++) {
1807  d_str[t] = val[t];
1808  }
1809  set_length(sz);
1810  set_read_p(true);
1811  return true;
1812  }
1813  else {
1814  return false;
1815  }
1816 }
1818 
1820 
1837 template <typename T>
1838 void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1839 {
1840  // unsigned long currentIndex;
1841 #if 0
1842  // Iterator version. Not tested, jhrg 8/14/13
1843  for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1844  unsigned long currentIndex = *i;
1845  if(currentIndex > (unsigned int)length()){
1846  stringstream s;
1847  s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1848  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1849  throw Error(s.str());
1850  }
1851  b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1852  }
1853 #endif
1854  for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1855  unsigned long currentIndex = (*indices)[i];
1856  if (currentIndex > (unsigned int)length()) {
1857  stringstream s;
1858  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1859  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1860  throw Error(s.str());
1861  }
1862  b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1863  }
1864 }
1865 void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1866 void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1867 void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1868 void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1869 void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1870 void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1871 void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1872 void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1873 void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1874 void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1875 
1876 #if 0
1877 template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1878 template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1879 template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1880 template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1881 template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1882 template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1883 template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1884 template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1885 template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1886 template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1887 #endif
1888 
1890 void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1891 {
1892  unsigned long currentIndex;
1893 
1894  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1895  for(unsigned long i=0; i<subsetIndex->size() ;++i){
1896  currentIndex = (*subsetIndex)[i] ;
1897  if(currentIndex > (unsigned int)length()){
1898  stringstream s;
1899  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1900  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1901  throw Error(s.str());
1902  }
1903  b[i] = d_str[currentIndex];
1904  }
1905  }
1906 }
1907 
1908 template <typename T>
1909 void Vector::value_worker(T *v) const
1910 {
1911  // Only copy if v is not null and the proto's type matches.
1912  // For Enums, use the element type since type == dods_enum_c.
1913  if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1914  memcpy(v, d_buf, length() * sizeof(T));
1915 }
1916 void Vector::value(dods_byte *b) const { value_worker(b); }
1917 void Vector::value(dods_int8 *b) const { value_worker(b); }
1918 void Vector::value(dods_int16 *b) const { value_worker(b); }
1919 void Vector::value(dods_uint16 *b) const { value_worker(b); }
1920 void Vector::value(dods_int32 *b) const { value_worker(b); }
1921 void Vector::value(dods_uint32 *b) const { value_worker(b); }
1922 void Vector::value(dods_int64 *b) const { value_worker(b); }
1923 void Vector::value(dods_uint64 *b) const { value_worker(b); }
1924 void Vector::value(dods_float32 *b) const { value_worker(b); }
1925 void Vector::value(dods_float64 *b) const { value_worker(b); }
1926 
1927 #if 0
1928 template void Vector::value(dods_byte *v) const;
1929 template void Vector::value(dods_int8 *v) const;
1930 template void Vector::value(dods_int16 *v) const;
1931 template void Vector::value(dods_uint16 *v) const;
1932 template void Vector::value(dods_int32 *v) const;
1933 template void Vector::value(dods_uint32 *v) const;
1934 template void Vector::value(dods_int64 *v) const;
1935 template void Vector::value(dods_uint64 *v) const;
1936 template void Vector::value(dods_float32 *v) const;
1937 template void Vector::value(dods_float64 *v) const;
1938 #endif
1939 
1940 
1942 void Vector::value(vector<string> &b) const
1943 {
1944  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1945  b = d_str;
1946 }
1947 
1951 {
1952  void *buffer = new char[width(true)];
1953 
1954  memcpy(buffer, d_buf, width(true));
1955 
1956  return buffer;
1957 }
1959 
1976 {
1977 #if 0
1978  // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1979  Vector::add_var_nocopy(v->ptr_duplicate(), p);
1980  add_var_nocopy(v->ptr_duplicate(), p);
1981  add_var_nocopy(v->ptr_duplicate());
1982 #else
1983  // Delete the current template variable
1984  if (d_proto) {
1985  delete d_proto;
1986  d_proto = 0;
1987  }
1988 
1989  // if 'v' is null, just set _var to null and exit.
1990  if (!v) {
1991  d_proto = 0;
1992  }
1993  else {
1994  // Jose Garcia
1995  // By getting a copy of this object to be assigned to _var
1996  // we let the owner of 'v' to deallocate it as necessary.
1997  d_proto = v->ptr_duplicate();
1998 
1999  // If 'v' has a name, use it as the name of the array. If v doesn't have
2000  // a name, then make sure to copy the array's name to it
2001  // so that software which uses the template's name will still work.
2002  if (!v->name().empty())
2003  set_name(v->name());
2004  else
2005  d_proto->set_name(name());
2006 
2007  d_proto->set_parent(this); // Vector --> child
2008 
2009  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
2010  << v->name() << " " << v->type_name() << ")" << endl);
2011  }
2012 #endif
2013 }
2014 
2015 void Vector::add_var_nocopy(BaseType * v, Part)
2016 {
2017  // Delete the current template variable
2018  if (d_proto) {
2019  delete d_proto;
2020  d_proto = 0;
2021  }
2022 
2023  // if 'v' is null, just set _var to null and exit.
2024  if (!v) {
2025  d_proto = 0;
2026  }
2027  else {
2028  d_proto = v;
2029 
2030  // If 'v' has a name, use it as the name of the array. If it *is*
2031  // empty, then make sure to copy the array's name to the template
2032  // so that software which uses the template's name will still work.
2033  if (!v->name().empty())
2034  set_name(v->name());
2035  else
2036  d_proto->set_name(name());
2037 
2038  d_proto->set_parent(this); // Vector is the parent; proto is the child
2039 
2040  DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2041  << v->name() << " " << v->type_name() << ")" << endl);
2042  }
2043 }
2044 
2045 bool Vector::check_semantics(string & msg, bool)
2046 {
2047  return BaseType::check_semantics(msg);
2048 }
2049 
2058 void Vector::dump(ostream &strm) const
2059 {
2060  strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2061  DapIndent::Indent();
2062  BaseType::dump(strm);
2063  strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2064  if (d_proto) {
2065  strm << DapIndent::LMarg << "base type:" << endl;
2066  DapIndent::Indent();
2067  d_proto->dump(strm);
2068  DapIndent::UnIndent();
2069  }
2070  else {
2071  strm << DapIndent::LMarg << "base type: not set" << endl;
2072  }
2073  strm << DapIndent::LMarg << "vector contents:" << endl;
2074  DapIndent::Indent();
2075  for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2076  if (d_compound_buf[i])
2077  d_compound_buf[i]->dump(strm);
2078  else
2079  strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2080  }
2081  DapIndent::UnIndent();
2082  strm << DapIndent::LMarg << "strings:" << endl;
2083  DapIndent::Indent();
2084  for (unsigned i = 0; i < d_str.size(); i++) {
2085  strm << DapIndent::LMarg << d_str[i] << endl;
2086  }
2087  DapIndent::UnIndent();
2088  if (d_buf) {
2089  switch (d_proto != 0 ? d_proto->type() : 0) {
2090  case dods_byte_c:
2091  case dods_char_c:
2092  strm << DapIndent::LMarg << "_buf: ";
2093  strm.write(d_buf, d_length);
2094  strm << endl;
2095  break;
2096 
2097  case 0:
2098  default:
2099  strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2100  break;
2101  }
2102  }
2103  else {
2104  strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2105  }
2106 
2107  DapIndent::UnIndent();
2108 }
2109 
2110 } // namespace libdap
2111 
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:890
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:471
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:311
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1341
virtual void dump(ostream &strm) const
dumps information about this object
Definition: BaseType.cc:282
Part
Names the parts of multi-section constructor data types.
Definition: Type.h:48
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:335
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:80
virtual unsigned int width(bool constrained=false) const
Returns the width of the data, in bytes.
Definition: Vector.cc:543
virtual void intern_data()
Read data into this variable.
Definition: Vector.cc:918
virtual void clear_local_data()
Definition: Vector.cc:1394
Read data from the stream made by D4StreamMarshaller.
virtual void compute_checksum(Crc32 &checksum)
include the data for this variable in the checksum DAP4 includes a checksum with every data response...
Definition: Vector.cc:875
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:392
Definition: crc.h:76
BaseType(const string &n, const Type &t, bool is_dap4=false)
The BaseType constructor.
Definition: BaseType.cc:125
virtual void add_var(BaseType *v, Part p=nil)
Add the BaseType pointer to this constructor type instance.
Definition: Vector.cc:1975
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:334
virtual void * value()
Definition: Vector.cc:1950
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:220
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition: Vector.cc:1529
virtual void put_vector_float32(char *val, int64_t num_elem)
Write a fixed size vector.
Type
Identifies the data type.
Definition: Type.h:94
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Serialize a Vector.
Definition: Vector.cc:670
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:724
A class for software fault reporting.
Definition: InternalErr.h:64
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:434
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Vector.cc:770
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:749
virtual void compute_checksum(Crc32 &checksum)=0
include the data for this variable in the checksum DAP4 includes a checksum with every data response...
Holds a DAP4 enumeration.
Definition: D4Enum.h:61
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:434
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4&#39;s receiv...
virtual void set_send_p(bool state)
Definition: BaseType.cc:559
virtual bool is_constructor_type() const
Returns true if the instance is a constructor (i.e., Structure, Sequence or Grid) type variable...
Definition: BaseType.cc:403
void set_vec_nocopy(unsigned int i, BaseType *val)
Sets element i to value val. Set the ith element to val. Extend the vector if needed.
Definition: Vector.cc:1357
bool m_is_cardinal_type() const
Definition: Vector.cc:124
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:356
virtual void reserve_value_capacity()
Definition: Vector.cc:1494
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:507
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition: Vector.cc:249
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer.
Definition: Vector.cc:1165
virtual bool check_semantics(string &msg, bool all=false)
Compare an object&#39;s current state with the semantics of its type.
Definition: Vector.cc:2045
void m_delete_cardinal_data_buffer()
Definition: Vector.cc:209
void AddData(const uint8_t *pData, const uint32_t length)
Definition: crc.h:98
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1421
Evaluate a constraint expression.
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:355
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:181
virtual void put_vector(char *val, int64_t num_bytes)
Write a fixed size vector.
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:370
virtual void set_name(const std::string &name)
Sets the name of the class instance.
Definition: Vector.cc:324
virtual int length() const
Definition: Vector.cc:555
virtual unsigned int buf2val(void **val)
Definition: Vector.cc:1261
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator and is called ...
virtual void set_length(int l)
Definition: Vector.cc:562
A class for error processing.
Definition: Error.h:90
virtual void put_vector_float64(char *val, int64_t num_elem)
Write a fixed size vector of float64s.
void vec_resize(int l)
Definition: Vector.cc:575
virtual unsigned int width(bool constrained=false) const
How many bytes does this use Return the number of bytes of storage this variable uses. For scalar types, this is pretty simple (an int32 uses 4 bytes, etc.). For arrays and Constructors, it is a bit more complex. Note that a scalar String variable uses sizeof(String*) bytes, not the length of the string. In other words, the value returned is independent of the type. Also note width() of a String array returns the number of elements in the array times sizeof(String*). That is, each different array size is a different data type.
Definition: BaseType.cc:1292
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Vector.cc:2058
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:349
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:1200