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