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