libdap  Updated for version 3.20.3
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 
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 
162  default:
163  assert("Vector::var: Unrecognized type");
164  return false;
165  }
166 }
167 
180 unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
181 {
182  // Make sure we HAVE a _var, or we cannot continue.
183  if (!d_proto) {
184  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
185  }
186 
187  // Make sure we only do this for the correct data types.
188  if (!m_is_cardinal_type()) {
189  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
190  }
191 
193 
194  // Handle this special case where this is an array that holds no values
195  if (numEltsOfType == 0)
196  return 0;
197 
198  // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
199  unsigned int bytesPerElt = d_proto->width();
200  unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
201  d_buf = new char[bytesNeeded];
202 
203  d_capacity = numEltsOfType;
204  return bytesNeeded;
205 }
206 
209 {
210  delete[] d_buf;
211  d_buf = 0;
212  d_capacity = 0;
213 }
214 
218 template<class CardType>
219 void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
220 {
221  if (numElts < 0) {
222  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
223  }
224  if (!fromArray) {
225  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
226  }
227  set_length(numElts);
229  memcpy(d_buf, fromArray, numElts * sizeof(CardType));
230  set_read_p(true);
231 }
232 
248 Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
249  BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
250 {
251  if (v)
252  add_var(v);
253 
254  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
255  if (d_proto)
256  d_proto->set_parent(this);
257 }
258 
277 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
278  BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
279 {
280  if (v)
281  add_var(v);
282 
283  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
284  if (d_proto)
285  d_proto->set_parent(this);
286 }
287 
289 Vector::Vector(const Vector & rhs) :
290  BaseType(rhs)
291 {
292  DBG2(cerr << "Entering Vector const ctor for object: " << this <<
293  endl); DBG2(cerr << "RHS: " << &rhs << endl);
294 
295  m_duplicate(rhs);
296 }
297 
298 Vector::~Vector()
299 {
300  DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
301 
302  delete d_proto;
303  d_proto = 0;
304 
305  // Clears all buffers
307 
308  DBG2(cerr << "Exiting ~Vector" << endl);
309 }
310 
311 Vector & Vector::operator=(const Vector & rhs)
312 {
313  if (this == &rhs)
314  return *this;
315 
316  dynamic_cast<BaseType &> (*this) = rhs;
317 
318  m_duplicate(rhs);
319 
320  return *this;
321 }
322 
323 void Vector::set_name(const std::string& name)
324 {
325  BaseType::set_name(name);
326  // We need to set the prototype name as well since
327  // this is what gets output in the dds! Otherwise, there's a mismatch.
328  if (d_proto) {
329  d_proto->set_name(name);
330  }
331 }
332 
333 int Vector::element_count(bool leaves)
334 {
335  if (!leaves)
336  return 1;
337  else
338  return d_proto->element_count(leaves);
339  // var() only works for simple types!
340  // jhrg 8/19/13 return var(0)->element_count(leaves);
341 }
342 
343 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
344 // from BaseType's version in that they set both the Vector object's copy of
345 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
346 // is a scalar, but does matter when it is an aggregate.
347 
354 void Vector::set_send_p(bool state)
355 {
356  if (d_proto) {
357  d_proto->set_send_p(state);
358 
359  // because some code may depend on the BaseType*s held in d_compound_buf
360  // behaving as if they are 'ordinary' DAP variables, make sure their send_p
361  // flag is set if they exist. Because space in the vector is allocated
362  // before values (BaseType*s) are added, check for nulls and limit the
363  // iteration to only those elements actually in the object including any
364  // constraints that may have been applied - these are values not declarations.
365  // jhrg 5/13/16
366  switch (d_proto->type()) {
367  case dods_structure_c:
368  case dods_sequence_c:
369  case dods_grid_c:
370  if (d_compound_buf.size() > 0) {
371  for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
372  if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
373  }
374  }
375  break;
376 
377  default:
378  break;
379  }
380  }
381 
382  BaseType::set_send_p(state);
383 }
384 
391 void Vector::set_read_p(bool state)
392 {
393  if (d_proto) {
394  d_proto->set_read_p(state);
395 
396  // See comment above.
397  switch (d_proto->type()) {
398  case dods_structure_c:
399  case dods_sequence_c:
400  case dods_grid_c:
401  if (d_compound_buf.size() > 0) {
402  for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
403  if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
404  }
405  }
406  break;
407 
408  default:
409  break;
410  }
411  }
412 
413  BaseType::set_read_p(state);
414 }
415 
433 BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
434 {
435  string name = www2id(n);
436  DBG2(cerr << "Vector::var: Looking for " << name << endl);
437 
438  if (name == "" || d_proto->name() == name) {
439  if (s)
440  s->push(this);
441  return d_proto;
442  }
443 
444  // If this is a Vector of constructor types, look for 'name' recursively.
445  // Make sure to check for the case where name is the default (the empty
446  // string). 9/1/98 jhrg
447  if (d_proto->is_constructor_type()) {
448  BaseType *result = d_proto->var(name, exact, s);
449  if (result && s)
450  s->push(this);
451  return result;
452  }
453 
454  return NULL;
455 }
456 
467 BaseType *Vector::var(const string & n, btp_stack & s)
468 {
469  string name = www2id(n);
470 
471  if (d_proto->is_constructor_type())
472  return d_proto->var(name, s);
473  else {
474  s.push((BaseType *) this);
475  return d_proto;
476  }
477 }
478 
490 BaseType *Vector::var(unsigned int i)
491 {
492 
493  switch (d_proto->type()) {
494  case dods_byte_c:
495  case dods_char_c:
496  case dods_int8_c:
497  case dods_uint8_c:
498  case dods_int16_c:
499  case dods_uint16_c:
500  case dods_int32_c:
501  case dods_uint32_c:
502  case dods_int64_c:
503  case dods_uint64_c:
504 
505  case dods_enum_c:
506 
507  case dods_float32_c:
508  case dods_float64_c:
509  // Transfer the ith value to the BaseType *d_proto
510  d_proto->val2buf(d_buf + (i * d_proto->width()));
511  return d_proto;
512 
513  case dods_str_c:
514  case dods_url_c:
515  d_proto->val2buf(&d_str[i]);
516  return d_proto;
517 
518  case dods_opaque_c:
519  case dods_array_c:
520  case dods_structure_c:
521  case dods_sequence_c:
522  case dods_grid_c:
523  return d_compound_buf[i];
524 
525  default:
526  throw Error ("Vector::var: Unrecognized type");
527  }
528 }
529 
536 unsigned int Vector::width(bool constrained) const
537 {
538  // Jose Garcia
539  assert(d_proto);
540 
541  return length() * d_proto->width(constrained);
542 }
543 
548 int Vector::length() const
549 {
550  return d_length;
551 }
552 
556 {
557  d_length = l;
558 }
559 
569 {
570  // I added this check, which alters the behavior of the method. jhrg 8/14/13
571  if (m_is_cardinal_type())
572  throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
573 
574  // Use resize() since other parts of the code use operator[]. Note that size() should
575  // be used when resize() is used. Using capacity() creates problems as noted in the
576  // comment in set_vec_nocopy(). jhrg 5/19/17
577  d_compound_buf.resize(l, 0); // Fill with NULLs
578  d_capacity = d_compound_buf.size(); // size in terms of number of elements.
579 }
580 
598 {
599  DBG(cerr << "Vector::intern_data: " << name() << endl);
600  if (!read_p())
601  read(); // read() throws Error and InternalErr
602 
603  // length() is not capacity; it must be set explicitly in read().
604  int num = length();
605 
606  switch (d_proto->type()) {
607  case dods_byte_c:
608  case dods_int16_c:
609  case dods_uint16_c:
610  case dods_int32_c:
611  case dods_uint32_c:
612  case dods_float32_c:
613  case dods_float64_c:
614  // For these cases, read() puts the data into d_buf,
615  // which is what we need.
616  break;
617 
618  case dods_str_c:
619  case dods_url_c:
620  // For these cases, read() will put the data into d_str[],
621  // which is also what we need.
622  break;
623 
624  case dods_array_c:
625  // This is an error since there can never be an Array of Array.
626  throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
627 
628  case dods_structure_c:
629  case dods_sequence_c:
630  case dods_grid_c:
631  DBG(cerr << "Vector::intern_data: found ctor" << endl);
632  // For these cases, we need to call read() for each of the 'num'
633  // elements in the 'd_compound_buf[]' array of BaseType object pointers.
634  //
635  // I changed the test here from '... = 0' to '... < num' to accommodate
636  // the case where the array is zero-length.
637  if (d_compound_buf.capacity() < (unsigned)num)
638  throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
639 
640  for (int i = 0; i < num; ++i)
641  d_compound_buf[i]->intern_data(eval, dds);
642 
643  break;
644 
645  default:
646  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
647  }
648 }
649 
661 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
662 {
663  // Added to streamline zero-length arrays. Not needed for correct function,
664  // but explicitly handling this case here makes the code easier to follow.
665  // In libdap::Vector::val2buf() there is a test that will catch the zero-length
666  // case as well. We still need to call serialize since it will write size
667  // information that the client depends on. jhrg 2/17/16
668  if (length() == 0)
669  set_read_p(true);
670  else if (!read_p())
671  read(); // read() throws Error and InternalErr
672 
673  if (ce_eval && !eval.eval_selection(dds, dataset()))
674  return true;
675 
676  // length() is not capacity; it must be set explicitly in read().
677  int num = length();
678 
679  bool status = false;
680 
681  switch (d_proto->type()) {
682  case dods_byte_c:
683  m.put_vector(d_buf, num, *this);
684  status = true;
685  break;
686 
687  case dods_int16_c:
688  case dods_uint16_c:
689  case dods_int32_c:
690  case dods_uint32_c:
691  case dods_float32_c:
692  case dods_float64_c:
693  m.put_vector(d_buf, num, d_proto->width(), *this);
694  status = true;
695 
696  break;
697 
698  case dods_str_c:
699  case dods_url_c:
700  if (d_str.capacity() == 0)
701  throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
702 
703  m.put_int(num);
704 
705  for (int i = 0; i < num; ++i)
706  m.put_str(d_str[i]);
707 
708  status = true;
709  break;
710 
711  case dods_array_c:
712  case dods_structure_c:
713  case dods_sequence_c:
714  case dods_grid_c:
715  //Jose Garcia
716  // Not setting the capacity of d_compound_buf is an internal error.
717  if (d_compound_buf.capacity() == 0)
718  throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
719 
720  m.put_int(num);
721  status = true;
722  for (int i = 0; i < num && status; ++i)
723  status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
724 
725  break;
726 
727  default:
728  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
729  }
730 
731 #ifdef CLEAR_LOCAL_DATA
733 #endif
734 
735  return status;
736 }
737 
738 // Read an object from the network and internalize it. For a Vector this is
739 // handled differently for a `cardinal' type. Vectors of Cardinals are
740 // stored using the `C' representations because these objects often are used
741 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
742 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
743 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
744 // Grid are vectors of the libdap Structure, ... classes).
745 //
746 // The boolean parameter REUSE determines whether internal storage is reused
747 // or not. If true, the _buf member is assumed to be large enough to hold the
748 // incoming cardinal data and is *not* reallocated. If false, new storage is
749 // allocated. If the internal buffer has not yet been allocated, then this
750 // parameter has no effect (i.e., storage is allocated). This parameter
751 // effects storage for cardinal data only.
752 //
753 // Returns: True is successful, false otherwise.
754 
755 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
756 {
757  unsigned int num;
758  unsigned i = 0;
759 
760  switch (d_proto->type()) {
761  case dods_byte_c:
762  case dods_int16_c:
763  case dods_uint16_c:
764  case dods_int32_c:
765  case dods_uint32_c:
766  case dods_float32_c:
767  case dods_float64_c:
768  um.get_int((int &) num);
769 
770  DBG(cerr << "Vector::deserialize: num = " << num << endl);
771  DBG(cerr << "Vector::deserialize: length = " << length() << endl);
772 
773  if (length() == -1)
774  set_length(num);
775 
776  if (num != (unsigned int) length())
777  throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
778 
779  if (!d_buf || !reuse) {
780  // Make d_buf be large enough for length() elements of _var->type()
781  // m_create...() deletes the old buffer.
783  DBG(cerr << "Vector::deserialize: allocating "
784  << width() << " bytes for an array of "
785  << length() << " " << d_proto->type_name() << endl);
786  }
787 
788  // Added to accommodate zero-length arrays.
789  // Note that the rest of the cases will just send the size without data
790  // but that these calls trigger error testing in the UnMarshaller code.
791  // jhrg 1/28/16
792  if (num == 0)
793  return true;
794 
795  if (d_proto->type() == dods_byte_c)
796  um.get_vector((char **) &d_buf, num, *this);
797  else
798  um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
799 
800  DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
801 
802  break;
803 
804  case dods_str_c:
805  case dods_url_c:
806  um.get_int((int &) num);
807 
808  if (length() == -1)
809  set_length(num);
810 
811  if (num != (unsigned int) length())
812  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
813 
814  d_str.resize((num > 0) ? num : 0); // Fill with NULLs
815  d_capacity = num; // capacity is number of strings we can fit.
816 
817  for (i = 0; i < num; ++i) {
818  string str;
819  um.get_str(str);
820  d_str[i] = str;
821 
822  }
823 
824  break;
825 
826  case dods_array_c:
827  // Added jhrg 5/18/17
828  // This replaces a comment that was simply 'TO DO'
829  throw InternalErr(__FILE__, __LINE__, "Array of array!");
830 
831  case dods_structure_c:
832  case dods_sequence_c:
833  case dods_grid_c:
834  um.get_int((int &) num);
835 
836  if (length() == -1)
837  set_length(num);
838 
839  if (num != (unsigned int) length())
840  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
841 
842  vec_resize(num);
843 
844  for (i = 0; i < num; ++i) {
845  d_compound_buf[i] = d_proto->ptr_duplicate();
846  d_compound_buf[i]->deserialize(um, dds);
847  }
848 
849  break;
850 
851  default:
852  throw InternalErr(__FILE__, __LINE__, "Unknown type!");
853  }
854 
855  return false;
856 }
857 
859 {
860  switch (d_proto->type()) {
861  case dods_byte_c:
862  case dods_char_c:
863  case dods_int8_c:
864  case dods_uint8_c:
865 
866  case dods_int16_c:
867  case dods_uint16_c:
868 
869  case dods_int32_c:
870  case dods_uint32_c:
871  case dods_float32_c:
872 
873  case dods_int64_c:
874  case dods_uint64_c:
875  case dods_float64_c:
876 
877  case dods_enum_c:
878  checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
879  break;
880 
881  case dods_str_c:
882  case dods_url_c:
883  for (int64_t i = 0, e = length(); i < e; ++i)
884  checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
885  break;
886 
887  case dods_opaque_c:
888  case dods_structure_c:
889  case dods_sequence_c:
890  d_proto->compute_checksum(checksum);
891  break;
892 
893  case dods_array_c: // No array of array
894  case dods_grid_c: // No grids in DAP4
895  default:
896  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
897  }
898 }
899 
900 void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
901 {
902  if (!read_p())
903  read(); // read() throws Error and InternalErr
904 
905  switch (d_proto->type()) {
906  case dods_byte_c:
907  case dods_char_c:
908  case dods_int8_c:
909  case dods_uint8_c:
910  case dods_int16_c:
911  case dods_uint16_c:
912  case dods_int32_c:
913  case dods_uint32_c:
914  case dods_int64_c:
915  case dods_uint64_c:
916 
917  case dods_enum_c:
918 
919  case dods_float32_c:
920  case dods_float64_c:
921 
922  case dods_str_c:
923  case dods_url_c:
924 #if 0
925  compute_checksum(checksum);
926 #endif
927  break;
928 
929  case dods_opaque_c:
930  case dods_structure_c:
931  case dods_sequence_c:
932  // Modified the assert here from '... != 0' to '... >= length())
933  // to accommodate the case of a zero-length array. jhrg 1/28/16
934  assert(d_compound_buf.capacity() >= (unsigned)length());
935 
936  for (int i = 0, e = length(); i < e; ++i)
937  d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
938  break;
939 
940  case dods_array_c: // No Array of Array in DAP4 either...
941  case dods_grid_c:
942  default:
943  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
944  }
945 }
946 
947 void
948 Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/)
949 {
950  if (!read_p())
951  read(); // read() throws Error and InternalErr
952 #if 0
953  if (filter && !eval.eval_selection(dmr, dataset()))
954  return true;
955 #endif
956  int64_t num = length(); // The constrained length in elements
957 
958  DBG(cerr << __func__ << ", num: " << num << endl);
959 
960  // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
961  if (num == 0)
962  return;
963 
964  switch (d_proto->type()) {
965  case dods_byte_c:
966  case dods_char_c:
967  case dods_int8_c:
968  case dods_uint8_c:
969  m.put_vector(d_buf, num);
970  break;
971 
972  case dods_int16_c:
973  case dods_uint16_c:
974  case dods_int32_c:
975  case dods_uint32_c:
976  case dods_int64_c:
977  case dods_uint64_c:
978  m.put_vector(d_buf, num, d_proto->width());
979  break;
980 
981  case dods_enum_c:
982  if (d_proto->width() == 1)
983  m.put_vector(d_buf, num);
984  else
985  m.put_vector(d_buf, num, d_proto->width());
986  break;
987 
988  case dods_float32_c:
989  m.put_vector_float32(d_buf, num);
990  break;
991 
992  case dods_float64_c:
993  m.put_vector_float64(d_buf, num);
994  break;
995 
996  case dods_str_c:
997  case dods_url_c:
998  assert((int64_t)d_str.capacity() >= num);
999 
1000  for (int64_t i = 0; i < num; ++i)
1001  m.put_str(d_str[i]);
1002 
1003  break;
1004 
1005  case dods_array_c:
1006  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1007 
1008  case dods_opaque_c:
1009  case dods_structure_c:
1010  case dods_sequence_c:
1011  assert(d_compound_buf.capacity() >= 0);
1012 
1013  for (int64_t i = 0; i < num; ++i) {
1014  DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
1015  d_compound_buf[i]->serialize(m, dmr, filter);
1016  }
1017 
1018  break;
1019 
1020  case dods_grid_c:
1021  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1022 
1023  default:
1024  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1025  }
1026 
1027 #ifdef CLEAR_LOCAL_DATA
1028  clear_local_data();
1029 #endif
1030 }
1031 
1032 void
1034 {
1035  if (m_is_cardinal_type()) {
1036  if (d_buf)
1038  if (!d_buf)
1040  }
1041 
1042  DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1043 
1044  // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1045  if (length() == 0)
1046  return;
1047 
1048  switch (d_proto->type()) {
1049  case dods_byte_c:
1050  case dods_char_c:
1051  case dods_int8_c:
1052  case dods_uint8_c:
1053  um.get_vector((char *)d_buf, length());
1054  break;
1055 
1056  case dods_int16_c:
1057  case dods_uint16_c:
1058  case dods_int32_c:
1059  case dods_uint32_c:
1060  case dods_int64_c:
1061  case dods_uint64_c:
1062  um.get_vector((char *)d_buf, length(), d_proto->width());
1063  break;
1064 
1065  case dods_enum_c:
1066  if (d_proto->width() == 1)
1067  um.get_vector((char *)d_buf, length());
1068  else
1069  um.get_vector((char *)d_buf, length(), d_proto->width());
1070  break;
1071 
1072  case dods_float32_c:
1073  um.get_vector_float32((char *)d_buf, length());
1074  break;
1075 
1076  case dods_float64_c:
1077  um.get_vector_float64((char *)d_buf, length());
1078  break;
1079 
1080  case dods_str_c:
1081  case dods_url_c: {
1082  int64_t len = length();
1083  d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1084  d_capacity = len; // capacity is number of strings we can fit.
1085 
1086  for (int64_t i = 0; i < len; ++i) {
1087  um.get_str(d_str[i]);
1088  }
1089 
1090  break;
1091  }
1092 
1093  case dods_array_c:
1094  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1095 
1096  case dods_opaque_c:
1097  case dods_structure_c:
1098  case dods_sequence_c: {
1099  vec_resize(length());
1100 
1101  for (int64_t i = 0, end = length(); i < end; ++i) {
1102  d_compound_buf[i] = d_proto->ptr_duplicate();
1103  d_compound_buf[i]->deserialize(um, dmr);
1104  }
1105 
1106  break;
1107  }
1108 
1109  case dods_grid_c:
1110  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1111 
1112  default:
1113  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1114  }
1115 }
1116 
1144 unsigned int Vector::val2buf(void *val, bool reuse)
1145 {
1146  // Jose Garcia
1147 
1148  // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1149  if (!val && length() == 0)
1150  return 0;
1151 
1152  // I *think* this method has been mainly designed to be use by read which
1153  // is implemented in the surrogate library. Passing NULL as a pointer to
1154  // this method will be an error of the creator of the surrogate library.
1155  // Even though I recognize the fact that some methods inside libdap++ can
1156  // call val2buf, I think by now no coding bugs such as misusing val2buf
1157  // will be in libdap++, so it will be an internal error from the
1158  // surrogate library.
1159  if (!val)
1160  throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1161 
1162  switch (d_proto->type()) {
1163  case dods_byte_c:
1164  case dods_char_c:
1165  case dods_int8_c:
1166  case dods_uint8_c:
1167  case dods_int16_c:
1168  case dods_uint16_c:
1169  case dods_int32_c:
1170  case dods_uint32_c:
1171  case dods_int64_c:
1172  case dods_uint64_c:
1173 
1174  case dods_enum_c:
1175 
1176  case dods_float32_c:
1177  case dods_float64_c:
1178 #if 0
1179  if (d_buf && !reuse)
1181 #endif
1182  // First time or no reuse (free'd above)
1183  if (!d_buf || !reuse)
1185 
1186  // width(true) returns the size in bytes given the constraint
1187  memcpy(d_buf, val, width(true));
1188  break;
1189 
1190  case dods_str_c:
1191  case dods_url_c:
1192  // Assume val points to an array of C++ string objects. Copy
1193  // them into the vector<string> field of this object.
1194  // Note: d_length is the number of elements in the Vector
1195  d_str.resize(d_length);
1196  d_capacity = d_length;
1197  for (int i = 0; i < d_length; ++i)
1198  d_str[i] = *(static_cast<string *> (val) + i);
1199 
1200  break;
1201 
1202  default:
1203  throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1204 
1205  }
1206 
1207  return width(true);
1208 }
1209 
1240 unsigned int Vector::buf2val(void **val)
1241 {
1242  // Jose Garcia
1243  // The same comment in Vector::val2buf applies here!
1244  if (!val)
1245  throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1246 
1247  unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1248 
1249  // This is the width computed using length(). The
1250  // length() property is changed when a projection
1251  // constraint is applied. Thus this is the number of
1252  // bytes in the buffer given the current constraint.
1253 
1254  switch (d_proto->type()) {
1255  case dods_byte_c:
1256  case dods_char_c:
1257  case dods_int8_c:
1258  case dods_uint8_c:
1259  case dods_int16_c:
1260  case dods_uint16_c:
1261  case dods_int32_c:
1262  case dods_uint32_c:
1263  case dods_int64_c:
1264  case dods_uint64_c:
1265 
1266  case dods_enum_c:
1267 
1268  case dods_float32_c:
1269  case dods_float64_c:
1270  if (!d_buf)
1271  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1272  if (!*val)
1273  *val = new char[wid];
1274 
1275  memcpy(*val, d_buf, wid);
1276  return wid;
1277 
1278  case dods_str_c:
1279  case dods_url_c: {
1280  if (d_str.empty())
1281  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1282  if (!*val)
1283  *val = new string[d_length];
1284 
1285  for (int i = 0; i < d_length; ++i)
1286  *(static_cast<string *> (*val) + i) = d_str[i];
1287 
1288  return width();
1289  }
1290 
1291  default:
1292  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1293  }
1294 
1295  //return wid;
1296 }
1297 
1318 void Vector::set_vec(unsigned int i, BaseType * val)
1319 {
1321 }
1322 
1334 void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1335 {
1336  // Jose Garcia
1337  // This is a public method which allows users to set the elements
1338  // of *this* vector. Passing an invalid index, a NULL pointer or
1339  // mismatching the vector type are internal errors.
1340  if (i >= static_cast<unsigned int> (d_length))
1341  throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1342  if (!val)
1343  throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1344  if (val->type() != d_proto->type())
1345  throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1346 
1347  // This code originally used capacity() instead of size(), but that was an error.
1348  // Use capacity() when using reserve() and size() when using resize(). Mixing
1349  // capacity() with resize() leaves holes in the data, where (pointer) values are
1350  // filled with nulls during successive calls to resize(). The resize() heuristic
1351  // remembers previous calls on a given vector<> and allocates larger than requested
1352  // blocks of memory on successive calls, which has the strange affect of erasing
1353  // values already in the vector in the parts just added.
1354  // jhrg 5/18/17
1355  if (i >= d_compound_buf.size()) {
1356  vec_resize(d_compound_buf.size() + 100);
1357  }
1358 
1359  d_compound_buf[i] = val;
1360 }
1361 
1372 {
1373  if (d_buf) {
1374  delete[] d_buf;
1375  d_buf = 0;
1376  }
1377 
1378  for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1379  delete d_compound_buf[i];
1380  d_compound_buf[i] = 0;
1381  }
1382 
1383  // Force memory to be reclaimed.
1384  d_compound_buf.resize(0);
1385  d_str.resize(0);
1386 
1387  d_capacity = 0;
1388  set_read_p(false);
1389 }
1390 
1398 unsigned int Vector::get_value_capacity() const
1399 {
1400  return d_capacity;
1401 }
1402 
1412 void Vector::reserve_value_capacity(unsigned int numElements)
1413 {
1414  if (!d_proto) {
1415  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1416  }
1417  switch (d_proto->type()) {
1418  case dods_byte_c:
1419  case dods_char_c:
1420  case dods_int8_c:
1421  case dods_uint8_c:
1422  case dods_int16_c:
1423  case dods_uint16_c:
1424  case dods_int32_c:
1425  case dods_uint32_c:
1426  case dods_int64_c:
1427  case dods_uint64_c:
1428 
1429  case dods_enum_c:
1430 
1431  case dods_float32_c:
1432  case dods_float64_c:
1433  // Make _buf be the right size and set _capacity
1435  break;
1436 
1437  case dods_str_c:
1438  case dods_url_c:
1439  // Make sure the d_str has enough room for all the strings.
1440  // Technically not needed, but it will speed things up for large arrays.
1441  d_str.reserve(numElements);
1442  d_capacity = numElements;
1443  break;
1444 
1445  case dods_array_c:
1446  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1447 
1448  case dods_opaque_c:
1449  case dods_structure_c:
1450  case dods_sequence_c:
1451  case dods_grid_c:
1452  // not clear anyone will go this path, but best to be complete.
1453  d_compound_buf.reserve(numElements);
1454  d_capacity = numElements;
1455  break;
1456 
1457  default:
1458  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1459  } // switch
1460 
1461 }
1462 
1469 {
1470  // Use the current length of the vector as the reserve amount.
1472 }
1473 
1502 unsigned int
1503 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1504 {
1505  static const string funcName = "set_value_slice_from_row_major_vector:";
1506 
1507  // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1508  Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1509 
1510  bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1511  if (!typesMatch) {
1512  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1513  }
1514 
1515  // Make sure the data exists
1516  if (!rowMajorData.read_p()) {
1517  throw InternalErr(__FILE__, __LINE__,
1518  funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1519  }
1520 
1521  // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1522  if (rowMajorData.length() < 0) {
1523  throw InternalErr(__FILE__, __LINE__,
1524  funcName
1525  + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1526  }
1527 
1528  // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1529  // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1530  if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1531  throw InternalErr(__FILE__, __LINE__,
1532  funcName
1533  + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1534  }
1535 
1536  // Make sure there's enough room in this Vector to store all the elements requested. Again,
1537  // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1538  if (d_capacity < (startElement + rowMajorData.length())) {
1539  throw InternalErr(__FILE__, __LINE__,
1540  funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1541  }
1542 
1543  // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1544  switch (d_proto->type()) {
1545  case dods_int8_c:
1546  case dods_uint8_c:
1547  case dods_byte_c:
1548  case dods_char_c:
1549  case dods_int16_c:
1550  case dods_uint16_c:
1551  case dods_int32_c:
1552  case dods_uint32_c:
1553  case dods_int64_c:
1554  case dods_uint64_c:
1555 
1556  case dods_enum_c:
1557 
1558  case dods_float32_c:
1559  case dods_float64_c: {
1560  if (!d_buf) {
1561  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1562  }
1563  if (!rowMajorData.d_buf) {
1564  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1565  }
1566  // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1567  int varWidth = d_proto->width();
1568  char* pFromBuf = rowMajorData.d_buf;
1569  int numBytesToCopy = rowMajorData.width(true);
1570  char* pIntoBuf = d_buf + (startElement * varWidth);
1571  memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1572  break;
1573  }
1574 
1575  case dods_str_c:
1576  case dods_url_c:
1577  // Strings need to be copied directly
1578  for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1579  d_str[startElement + i] = rowMajorData.d_str[i];
1580  }
1581  break;
1582 
1583  case dods_array_c:
1584  case dods_opaque_c:
1585  case dods_structure_c:
1586  case dods_sequence_c:
1587  case dods_grid_c:
1588  // Not sure that this function will be used for these type of nested objects, so I will throw here.
1589  throw InternalErr(__FILE__, __LINE__,
1590  funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1591 
1592  default:
1593  throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1594  } // switch (_var->type())
1595 
1596  // This is how many elements we copied.
1597  return (unsigned int) rowMajorData.length();
1598 }
1599 
1608 template <typename T>
1609 static bool types_match(Type t, T *cpp_var)
1610 {
1611  switch (t) {
1612  case dods_byte_c:
1613  case dods_char_c:
1614  case dods_uint8_c:
1615  return typeid(cpp_var) == typeid(dods_byte*);
1616 
1617  case dods_int8_c:
1618  return typeid(cpp_var) == typeid(dods_int8*);
1619  case dods_int16_c:
1620  return typeid(cpp_var) == typeid(dods_int16*);
1621  case dods_uint16_c:
1622  return typeid(cpp_var) == typeid(dods_uint16*);
1623  case dods_int32_c:
1624  return typeid(cpp_var) == typeid(dods_int32*);
1625  case dods_uint32_c:
1626  return typeid(cpp_var) == typeid(dods_uint32*);
1627  case dods_int64_c:
1628  return typeid(cpp_var) == typeid(dods_int64*);
1629  case dods_uint64_c:
1630  return typeid(cpp_var) == typeid(dods_uint64*);
1631 
1632  case dods_float32_c:
1633  return typeid(cpp_var) == typeid(dods_float32*);
1634  case dods_float64_c:
1635  return typeid(cpp_var) == typeid(dods_float64*);
1636 
1637  case dods_null_c:
1638  case dods_enum_c:
1639  case dods_str_c:
1640  case dods_url_c:
1641  case dods_opaque_c:
1642  case dods_array_c:
1643  case dods_structure_c:
1644  case dods_sequence_c:
1645  case dods_group_c:
1646  default:
1647  return false;
1648  }
1649 }
1650 
1652 
1654 template <typename T>
1655 bool Vector::set_value_worker(T *v, int sz)
1656 {
1657  if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1658  return false;
1659 
1661  return true;
1662 }
1663 
1664 bool Vector::set_value(dods_byte *val, int sz)
1665 {
1666  return set_value_worker(val, sz);
1667 }
1668 bool Vector::set_value(dods_int8 *val, int sz)
1669 {
1670  return set_value_worker(val, sz);
1671 }
1672 bool Vector::set_value(dods_int16 *val, int sz)
1673 {
1674  return set_value_worker(val, sz);
1675 }
1676 bool Vector::set_value(dods_uint16 *val, int sz)
1677 {
1678  return set_value_worker(val, sz);
1679 }
1680 bool Vector::set_value(dods_int32 *val, int sz)
1681 {
1682  return set_value_worker(val, sz);
1683 }
1684 bool Vector::set_value(dods_uint32 *val, int sz)
1685 {
1686  return set_value_worker(val, sz);
1687 }
1688 bool Vector::set_value(dods_int64 *val, int sz)
1689 {
1690  return set_value_worker(val, sz);
1691 }
1692 bool Vector::set_value(dods_uint64 *val, int sz)
1693 {
1694  return set_value_worker(val, sz);
1695 }
1696 bool Vector::set_value(dods_float32 *val, int sz)
1697 {
1698  return set_value_worker(val, sz);
1699 }
1700 bool Vector::set_value(dods_float64 *val, int sz)
1701 {
1702  return set_value_worker(val, sz);
1703 }
1704 
1706 bool Vector::set_value(string *val, int sz)
1707 {
1708  if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1709  d_str.resize(sz);
1710  d_capacity = sz;
1711  for (register int t = 0; t < sz; t++) {
1712  d_str[t] = val[t];
1713  }
1714  set_length(sz);
1715  set_read_p(true);
1716  return true;
1717  }
1718  else {
1719  return false;
1720  }
1721 }
1722 
1723 template<typename T>
1724 bool Vector::set_value_worker(vector<T> &v, int sz)
1725 {
1726  return set_value(&v[0], sz);
1727 }
1728 
1729 bool Vector::set_value(vector<dods_byte> &val, int sz)
1730 {
1731  return set_value_worker(val, sz);
1732 }
1733 bool Vector::set_value(vector<dods_int8> &val, int sz)
1734 {
1735  return set_value_worker(val, sz);
1736 }
1737 bool Vector::set_value(vector<dods_int16> &val, int sz)
1738 {
1739  return set_value_worker(val, sz);
1740 }
1741 bool Vector::set_value(vector<dods_uint16> &val, int sz)
1742 {
1743  return set_value_worker(val, sz);
1744 }
1745 bool Vector::set_value(vector<dods_int32> &val, int sz)
1746 {
1747  return set_value_worker(val, sz);
1748 }
1749 bool Vector::set_value(vector<dods_uint32> &val, int sz)
1750 {
1751  return set_value_worker(val, sz);
1752 }
1753 bool Vector::set_value(vector<dods_int64> &val, int sz)
1754 {
1755  return set_value_worker(val, sz);
1756 }
1757 bool Vector::set_value(vector<dods_uint64> &val, int sz)
1758 {
1759  return set_value_worker(val, sz);
1760 }
1761 bool Vector::set_value(vector<dods_float32> &val, int sz)
1762 {
1763  return set_value_worker(val, sz);
1764 }
1765 bool Vector::set_value(vector<dods_float64> &val, int sz)
1766 {
1767  return set_value_worker(val, sz);
1768 }
1769 
1770 
1772 bool Vector::set_value(vector<string> &val, int sz)
1773 {
1774  if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1775  d_str.resize(sz);
1776  d_capacity = sz;
1777  for (register int t = 0; t < sz; t++) {
1778  d_str[t] = val[t];
1779  }
1780  set_length(sz);
1781  set_read_p(true);
1782  return true;
1783  }
1784  else {
1785  return false;
1786  }
1787 }
1789 
1791 
1808 template <typename T>
1809 void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1810 {
1811  // unsigned long currentIndex;
1812 #if 0
1813  // Iterator version. Not tested, jhrg 8/14/13
1814  for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1815  unsigned long currentIndex = *i;
1816  if(currentIndex > (unsigned int)length()){
1817  stringstream s;
1818  s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1819  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1820  throw Error(s.str());
1821  }
1822  b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1823  }
1824 #endif
1825  for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1826  unsigned long currentIndex = (*indices)[i];
1827  if (currentIndex > (unsigned int)length()) {
1828  stringstream s;
1829  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1830  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1831  throw Error(s.str());
1832  }
1833  b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1834  }
1835 }
1836 void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1837 void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1838 void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1839 void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1840 void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1841 void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1842 void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1843 void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1844 void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1845 void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1846 
1847 #if 0
1848 template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1849 template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1850 template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1851 template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1852 template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1853 template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1854 template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1855 template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1856 template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1857 template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1858 #endif
1859 
1861 void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1862 {
1863  unsigned long currentIndex;
1864 
1865  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1866  for(unsigned long i=0; i<subsetIndex->size() ;++i){
1867  currentIndex = (*subsetIndex)[i] ;
1868  if(currentIndex > (unsigned int)length()){
1869  stringstream s;
1870  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1871  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1872  throw Error(s.str());
1873  }
1874  b[i] = d_str[currentIndex];
1875  }
1876  }
1877 }
1878 
1879 template <typename T>
1880 void Vector::value_worker(T *v) const
1881 {
1882  // Only copy if v is not null and the proto's type matches.
1883  // For Enums, use the element type since type == dods_enum_c.
1884  if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1885  memcpy(v, d_buf, length() * sizeof(T));
1886 }
1887 void Vector::value(dods_byte *b) const { value_worker(b); }
1888 void Vector::value(dods_int8 *b) const { value_worker(b); }
1889 void Vector::value(dods_int16 *b) const { value_worker(b); }
1890 void Vector::value(dods_uint16 *b) const { value_worker(b); }
1891 void Vector::value(dods_int32 *b) const { value_worker(b); }
1892 void Vector::value(dods_uint32 *b) const { value_worker(b); }
1893 void Vector::value(dods_int64 *b) const { value_worker(b); }
1894 void Vector::value(dods_uint64 *b) const { value_worker(b); }
1895 void Vector::value(dods_float32 *b) const { value_worker(b); }
1896 void Vector::value(dods_float64 *b) const { value_worker(b); }
1897 
1898 #if 0
1899 template void Vector::value(dods_byte *v) const;
1900 template void Vector::value(dods_int8 *v) const;
1901 template void Vector::value(dods_int16 *v) const;
1902 template void Vector::value(dods_uint16 *v) const;
1903 template void Vector::value(dods_int32 *v) const;
1904 template void Vector::value(dods_uint32 *v) const;
1905 template void Vector::value(dods_int64 *v) const;
1906 template void Vector::value(dods_uint64 *v) const;
1907 template void Vector::value(dods_float32 *v) const;
1908 template void Vector::value(dods_float64 *v) const;
1909 #endif
1910 
1911 
1913 void Vector::value(vector<string> &b) const
1914 {
1915  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1916  b = d_str;
1917 }
1918 
1922 {
1923  void *buffer = new char[width(true)];
1924 
1925  memcpy(buffer, d_buf, width(true));
1926 
1927  return buffer;
1928 }
1930 
1947 {
1948 #if 0
1949  // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1950  Vector::add_var_nocopy(v->ptr_duplicate(), p);
1951  add_var_nocopy(v->ptr_duplicate(), p);
1952  add_var_nocopy(v->ptr_duplicate());
1953 #else
1954  // Delete the current template variable
1955  if (d_proto) {
1956  delete d_proto;
1957  d_proto = 0;
1958  }
1959 
1960  // if 'v' is null, just set _var to null and exit.
1961  if (!v) {
1962  d_proto = 0;
1963  }
1964  else {
1965  // Jose Garcia
1966  // By getting a copy of this object to be assigned to _var
1967  // we let the owner of 'v' to deallocate it as necessary.
1968  d_proto = v->ptr_duplicate();
1969 
1970  // If 'v' has a name, use it as the name of the array. If v doesn't have
1971  // a name, then make sure to copy the array's name to it
1972  // so that software which uses the template's name will still work.
1973  if (!v->name().empty())
1974  set_name(v->name());
1975  else
1976  d_proto->set_name(name());
1977 
1978  d_proto->set_parent(this); // Vector --> child
1979 
1980  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1981  << v->name() << " " << v->type_name() << ")" << endl);
1982  }
1983 #endif
1984 }
1985 
1986 void Vector::add_var_nocopy(BaseType * v, Part)
1987 {
1988  // Delete the current template variable
1989  if (d_proto) {
1990  delete d_proto;
1991  d_proto = 0;
1992  }
1993 
1994  // if 'v' is null, just set _var to null and exit.
1995  if (!v) {
1996  d_proto = 0;
1997  }
1998  else {
1999  d_proto = v;
2000 
2001  // If 'v' has a name, use it as the name of the array. If it *is*
2002  // empty, then make sure to copy the array's name to the template
2003  // so that software which uses the template's name will still work.
2004  if (!v->name().empty())
2005  set_name(v->name());
2006  else
2007  d_proto->set_name(name());
2008 
2009  d_proto->set_parent(this); // Vector is the parent; proto is the child
2010 
2011  DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2012  << v->name() << " " << v->type_name() << ")" << endl);
2013  }
2014 }
2015 
2016 bool Vector::check_semantics(string & msg, bool)
2017 {
2018  return BaseType::check_semantics(msg);
2019 }
2020 
2029 void Vector::dump(ostream &strm) const
2030 {
2031  strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2032  DapIndent::Indent();
2033  BaseType::dump(strm);
2034  strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2035  if (d_proto) {
2036  strm << DapIndent::LMarg << "base type:" << endl;
2037  DapIndent::Indent();
2038  d_proto->dump(strm);
2039  DapIndent::UnIndent();
2040  }
2041  else {
2042  strm << DapIndent::LMarg << "base type: not set" << endl;
2043  }
2044  strm << DapIndent::LMarg << "vector contents:" << endl;
2045  DapIndent::Indent();
2046  for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2047  if (d_compound_buf[i])
2048  d_compound_buf[i]->dump(strm);
2049  else
2050  strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2051  }
2052  DapIndent::UnIndent();
2053  strm << DapIndent::LMarg << "strings:" << endl;
2054  DapIndent::Indent();
2055  for (unsigned i = 0; i < d_str.size(); i++) {
2056  strm << DapIndent::LMarg << d_str[i] << endl;
2057  }
2058  DapIndent::UnIndent();
2059  if (d_buf) {
2060  switch (d_proto != 0 ? d_proto->type() : 0) {
2061  case dods_byte_c:
2062  case dods_char_c:
2063  strm << DapIndent::LMarg << "_buf: ";
2064  strm.write(d_buf, d_length);
2065  strm << endl;
2066  break;
2067 
2068  case 0:
2069  default:
2070  strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2071  break;
2072  }
2073  }
2074  else {
2075  strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2076  }
2077 
2078  DapIndent::UnIndent();
2079 }
2080 
2081 } // namespace libdap
2082 
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:1318
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:536
virtual void intern_data()
Read data into this variable.
Definition: Vector.cc:900
virtual void clear_local_data()
Definition: Vector.cc:1371
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:858
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:391
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:1946
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:333
virtual void * value()
Definition: Vector.cc:1921
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:219
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition: Vector.cc:1503
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:661
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:433
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Vector.cc:755
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:1334
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:1468
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:248
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer.
Definition: Vector.cc:1144
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:2016
void m_delete_cardinal_data_buffer()
Definition: Vector.cc:208
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:1398
Evaluate a constraint expression.
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:354
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:180
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:323
virtual int length() const
Definition: Vector.cc:548
virtual unsigned int buf2val(void **val)
Definition: Vector.cc:1240
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:555
A class for error processing.
Definition: Error.h:92
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:568
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:2029
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