libdap  Updated for version 3.17.2
Vector.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 // (c) COPYRIGHT URI/MIT 1995-1999
26 // Please read the full copyright statement in the file COPYRIGHT_URI.
27 //
28 // Authors:
29 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu>
30 
31 // Implementation for class Vector. This class is the basis for all the
32 // vector-type classes in libdap's <Array, List>.
33 //
34 // 11/21/95 jhrg
35 
36 #include "config.h"
37 
38 #include <cstring>
39 #include <cassert>
40 
41 //#define DODS_DEBUG 1
42 
43 #include <sstream>
44 #include <vector>
45 #include <algorithm>
46 #include <typeinfo>
47 
48 #include <stdint.h>
49 
50 #include "crc.h"
51 
52 #include "Vector.h"
53 #include "Marshaller.h"
54 #include "UnMarshaller.h"
55 
56 #include "D4StreamMarshaller.h"
57 #include "D4StreamUnMarshaller.h"
58 
59 #include "D4Enum.h"
60 
61 #include "Type.h"
62 #include "dods-datatypes.h"
63 #include "escaping.h"
64 #include "util.h"
65 #include "debug.h"
66 #include "InternalErr.h"
67 
68 #undef CLEAR_LOCAL_DATA
69 
70 using std::cerr;
71 using std::endl;
72 
73 namespace libdap {
74 
75 void Vector::m_duplicate(const Vector & v)
76 {
77  d_length = v.d_length;
78 
79  // _var holds the type of the elements. That is, it holds a BaseType
80  // which acts as a template for the type of each element.
81  if (v.d_proto) {
82  d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
83  d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
84  }
85  else {
86  d_proto = 0;
87  }
88 
89  // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
90  // d_compound_buf is used when the Vector holds non-numeric data (including strings
91  // although it used to be that was not the case jhrg 2/10/05) while d_buf
92  // holds numeric values.
93  if (v.d_compound_buf.empty()) {
94  d_compound_buf = v.d_compound_buf;
95  }
96  else {
97  // Failure to set the size will make the [] operator barf on the LHS
98  // of the assignment inside the loop.
99  d_compound_buf.resize(d_length);
100  for (int i = 0; i < d_length; ++i) {
101  // There's no need to call set_parent() for each element; we
102  // maintain the back pointer using the d_proto member. These
103  // instances are used to hold _values_ only while the d_proto
104  // field holds the type information for the elements.
105  d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
106  }
107  }
108 
109  // copy the strings. This copies the values.
110  d_str = v.d_str;
111 
112  // copy numeric values if there are any.
113  d_buf = 0; // init to null
114  if (v.d_buf) // only copy if data present
115  val2buf(v.d_buf); // store v's value in this's _BUF.
116 
117  d_capacity = v.d_capacity;
118 }
119 
125 {
126  // Not cardinal if no d_proto at all!
127  if (!d_proto) {
128  return false;
129  }
130 
131  switch (d_proto->type()) {
132  case dods_byte_c:
133  case dods_char_c:
134  case dods_int16_c:
135  case dods_uint16_c:
136  case dods_int32_c:
137  case dods_uint32_c:
138  case dods_float32_c:
139  case dods_float64_c:
140  // New cardinal types for DAP4
141  case dods_int8_c:
142  case dods_uint8_c:
143  case dods_int64_c:
144  case dods_uint64_c:
145 
146  case dods_enum_c:
147  return true;
148  break;
149 
150  // These must be handled differently.
151  case dods_str_c:
152  case dods_url_c:
153  case dods_opaque_c:
154 
155  case dods_array_c:
156 
157  case dods_structure_c:
158  case dods_sequence_c:
159  case dods_grid_c:
160  return false;
161  break;
162 
163  default:
164  assert("Vector::var: Unrecognized type");
165  return false;
166  }
167 }
168 
181 unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
182 {
183  // Make sure we HAVE a _var, or we cannot continue.
184  if (!d_proto) {
185  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
186  }
187 
188  // Make sure we only do this for the correct data types.
189  if (!m_is_cardinal_type()) {
190  throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
191  }
192 
194 
195  // Handle this special case where this is an array that holds no values
196  if (numEltsOfType == 0)
197  return 0;
198 
199  // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
200  unsigned int bytesPerElt = d_proto->width();
201  unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
202  d_buf = new char[bytesNeeded];
203 
204  d_capacity = numEltsOfType;
205  return bytesNeeded;
206 }
207 
210 {
211  delete[] d_buf;
212  d_buf = 0;
213  d_capacity = 0;
214 }
215 
219 template<class CardType>
220 void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
221 {
222  if (numElts < 0) {
223  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
224  }
225  if (!fromArray) {
226  throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
227  }
228  set_length(numElts);
230  memcpy(d_buf, fromArray, numElts * sizeof(CardType));
231  set_read_p(true);
232 }
233 
249 Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
250  BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
251 {
252  if (v)
253  add_var(v);
254 
255  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
256  if (d_proto)
257  d_proto->set_parent(this);
258 }
259 
278 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
279  BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
280 {
281  if (v)
282  add_var(v);
283 
284  DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
285  if (d_proto)
286  d_proto->set_parent(this);
287 }
288 
290 Vector::Vector(const Vector & rhs) :
291  BaseType(rhs)
292 {
293  DBG2(cerr << "Entering Vector const ctor for object: " << this <<
294  endl); DBG2(cerr << "RHS: " << &rhs << endl);
295 
296  m_duplicate(rhs);
297 }
298 
299 Vector::~Vector()
300 {
301  DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
302 
303  delete d_proto;
304  d_proto = 0;
305 
306  // Clears all buffers
308 
309  DBG2(cerr << "Exiting ~Vector" << endl);
310 }
311 
312 Vector & Vector::operator=(const Vector & rhs)
313 {
314  if (this == &rhs)
315  return *this;
316 
317  dynamic_cast<BaseType &> (*this) = rhs;
318 
319  m_duplicate(rhs);
320 
321  return *this;
322 }
323 
324 void Vector::set_name(const std::string& name)
325 {
326  BaseType::set_name(name);
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  d_proto->set_send_p(state);
358  BaseType::set_send_p(state);
359 }
360 
367 void Vector::set_read_p(bool state)
368 {
369  if (d_proto) {
370  d_proto->set_read_p(state);
371  }
372  BaseType::set_read_p(state);
373 }
374 
392 BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
393 {
394  string name = www2id(n);
395  DBG2(cerr << "Vector::var: Looking for " << name << endl);
396 
397  // If this is a Vector of constructor types, look for 'name' recursively.
398  // Make sure to check for the case where name is the default (the empty
399  // string). 9/1/98 jhrg
400  if (d_proto->is_constructor_type()) {
401  if (name == "" || d_proto->name() == name) {
402  if (s)
403  s->push(this);
404  return d_proto;
405  }
406  else {
407  BaseType * result = d_proto->var(name, exact, s);
408  if (result && s)
409  s->push(this);
410  return result;
411  }
412  }
413  else {
414  return d_proto;
415  }
416 }
417 
428 BaseType *Vector::var(const string & n, btp_stack & s)
429 {
430  string name = www2id(n);
431 
432  if (d_proto->is_constructor_type())
433  return d_proto->var(name, s);
434  else {
435  s.push((BaseType *) this);
436  return d_proto;
437  }
438 }
439 
451 BaseType *Vector::var(unsigned int i)
452 {
453 
454  switch (d_proto->type()) {
455  case dods_byte_c:
456  case dods_char_c:
457  case dods_int8_c:
458  case dods_uint8_c:
459  case dods_int16_c:
460  case dods_uint16_c:
461  case dods_int32_c:
462  case dods_uint32_c:
463  case dods_int64_c:
464  case dods_uint64_c:
465 
466  case dods_enum_c:
467 
468  case dods_float32_c:
469  case dods_float64_c:
470  // Transfer the ith value to the BaseType *d_proto
471  d_proto->val2buf(d_buf + (i * d_proto->width()));
472  return d_proto;
473  break;
474 
475  case dods_str_c:
476  case dods_url_c:
477  d_proto->val2buf(&d_str[i]);
478  return d_proto;
479  break;
480 
481  case dods_opaque_c:
482  case dods_array_c:
483  case dods_structure_c:
484  case dods_sequence_c:
485  case dods_grid_c:
486  return d_compound_buf[i];
487  break;
488 
489  default:
490  throw Error ("Vector::var: Unrecognized type");
491  break;
492  }
493 
494  return 0;
495 }
496 
503 unsigned int Vector::width(bool constrained) const
504 {
505  // Jose Garcia
506  assert(d_proto);
507 
508  return length() * d_proto->width(constrained);
509 }
510 
515 int Vector::length() const
516 {
517  return d_length;
518 }
519 
523 {
524  d_length = l;
525 }
526 
536 {
537  // I added this check, which alters the behavior of the method. jhrg 8/14/13
538  if (m_is_cardinal_type())
539  throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
540 
541  d_compound_buf.resize((l > 0) ? l : 0, 0); // Fill with NULLs
542  d_capacity = l; // capacity in terms of number of elements.
543 }
544 
562 {
563  DBG(cerr << "Vector::intern_data: " << name() << endl);
564  if (!read_p())
565  read(); // read() throws Error and InternalErr
566 
567  // length() is not capacity; it must be set explicitly in read().
568  int num = length();
569 
570  switch (d_proto->type()) {
571  case dods_byte_c:
572  case dods_int16_c:
573  case dods_uint16_c:
574  case dods_int32_c:
575  case dods_uint32_c:
576  case dods_float32_c:
577  case dods_float64_c:
578  // For these cases, read() puts the data into d_buf,
579  // which is what we need.
580  break;
581 
582  case dods_str_c:
583  case dods_url_c:
584  // For these cases, read() will put the data into d_str[],
585  // which is also what we need.
586  break;
587 
588  case dods_array_c:
589  // This is an error since there can never be an Array of Array.
590  throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
591  break;
592 
593  case dods_structure_c:
594  case dods_sequence_c:
595  case dods_grid_c:
596  DBG(cerr << "Vector::intern_data: found ctor" << endl);
597  // For these cases, we need to call read() for each of the 'num'
598  // elements in the 'd_compound_buf[]' array of BaseType object pointers.
599  //
600  // I changed the test here from '... = 0' to '... < num' to accommodate
601  // the case where the array is zero-length.
602  if (d_compound_buf.capacity() < (unsigned)num)
603  throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
604 
605  for (int i = 0; i < num; ++i)
606  d_compound_buf[i]->intern_data(eval, dds);
607 
608  break;
609 
610  default:
611  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
612  break;
613  }
614 }
615 
627 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
628 {
629 #if 0
630  dds.timeout_on();
631 #endif
632  // Added to streamline zero-length arrays. Not needed for correct function,
633  // but explicitly handling this case here makes the code easier to follow.
634  // In libdap::Vector::val2buf() there is a test that will catch the zero-length
635  // case as well. We still need to call serialize since it will write size
636  // information that the client depends on. jhrg 2/17/16
637  if (length() == 0)
638  set_read_p(true);
639  else if (!read_p())
640  read(); // read() throws Error and InternalErr
641 
642  if (ce_eval && !eval.eval_selection(dds, dataset()))
643  return true;
644 #if 0
645  dds.timeout_off();
646 #endif
647  // length() is not capacity; it must be set explicitly in read().
648  int num = length();
649 
650  bool status = false;
651 
652  switch (d_proto->type()) {
653  case dods_byte_c:
654  m.put_vector(d_buf, num, *this);
655  status = true;
656  break;
657 
658  case dods_int16_c:
659  case dods_uint16_c:
660  case dods_int32_c:
661  case dods_uint32_c:
662  case dods_float32_c:
663  case dods_float64_c:
664  m.put_vector(d_buf, num, d_proto->width(), *this);
665  status = true;
666 
667  break;
668 
669  case dods_str_c:
670  case dods_url_c:
671  if (d_str.capacity() == 0)
672  throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
673 
674  m.put_int(num);
675 
676  for (int i = 0; i < num; ++i)
677  m.put_str(d_str[i]);
678 
679  status = true;
680  break;
681 
682  case dods_array_c:
683  case dods_structure_c:
684  case dods_sequence_c:
685  case dods_grid_c:
686  //Jose Garcia
687  // Not setting the capacity of d_compound_buf is an internal error.
688  if (d_compound_buf.capacity() == 0)
689  throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
690 
691  m.put_int(num);
692  status = true;
693  for (int i = 0; i < num && status; ++i)
694  status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
695 
696  break;
697 
698  default:
699  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
700  break;
701  }
702 
703 #ifdef CLEAR_LOCAL_DATA
705 #endif
706 
707  return status;
708 }
709 
710 // Read an object from the network and internalize it. For a Vector this is
711 // handled differently for a `cardinal' type. Vectors of Cardinals are
712 // stored using the `C' representations because these objects often are used
713 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
714 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
715 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
716 // Grid are vectors of the libdap Structure, ... classes).
717 //
718 // The boolean parameter REUSE determines whether internal storage is reused
719 // or not. If true, the _buf member is assumed to be large enough to hold the
720 // incoming cardinal data and is *not* reallocated. If false, new storage is
721 // allocated. If the internal buffer has not yet been allocated, then this
722 // parameter has no effect (i.e., storage is allocated). This parameter
723 // effects storage for cardinal data only.
724 //
725 // Returns: True is successful, false otherwise.
726 
727 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
728 {
729  unsigned int num;
730  unsigned i = 0;
731 
732  switch (d_proto->type()) {
733  case dods_byte_c:
734  case dods_int16_c:
735  case dods_uint16_c:
736  case dods_int32_c:
737  case dods_uint32_c:
738  case dods_float32_c:
739  case dods_float64_c:
740  um.get_int((int &) num);
741 
742  DBG(cerr << "Vector::deserialize: num = " << num << endl);
743  DBG(cerr << "Vector::deserialize: length = " << length() << endl);
744 
745  if (length() == -1)
746  set_length(num);
747 
748  if (num != (unsigned int) length())
749  throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
750 
751  if (!d_buf || !reuse) {
752  // Make d_buf be large enough for length() elements of _var->type()
753  // m_create...() deletes the old buffer.
755  DBG(cerr << "Vector::deserialize: allocating "
756  << width() << " bytes for an array of "
757  << length() << " " << d_proto->type_name() << endl);
758  }
759 
760  // Added to accommodate zero-length arrays.
761  // Note that the rest of the cases will just send the size without data
762  // but that these calls trigger error testing in the UnMarshaller code.
763  // jhrg 1/28/16
764  if (num == 0)
765  return true;
766 
767  if (d_proto->type() == dods_byte_c)
768  um.get_vector((char **) &d_buf, num, *this);
769  else
770  um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
771 
772  DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
773 
774  break;
775 
776  case dods_str_c:
777  case dods_url_c:
778  um.get_int((int &) num);
779 
780  if (length() == -1)
781  set_length(num);
782 
783  if (num != (unsigned int) length())
784  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
785 
786  d_str.resize((num > 0) ? num : 0); // Fill with NULLs
787  d_capacity = num; // capacity is number of strings we can fit.
788 
789  for (i = 0; i < num; ++i) {
790  string str;
791  um.get_str(str);
792  d_str[i] = str;
793 
794  }
795 
796  break;
797 
798  case dods_array_c:
799  // TODO
800  case dods_structure_c:
801  case dods_sequence_c:
802  case dods_grid_c:
803  um.get_int((int &) num);
804 
805  if (length() == -1)
806  set_length(num);
807 
808  if (num != (unsigned int) length())
809  throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
810 
811  vec_resize(num);
812 
813  for (i = 0; i < num; ++i) {
814  d_compound_buf[i] = d_proto->ptr_duplicate();
815  d_compound_buf[i]->deserialize(um, dds);
816  }
817 
818  break;
819 
820  default:
821  throw InternalErr(__FILE__, __LINE__, "Unknown type!");
822  break;
823  }
824 
825  return false;
826 }
827 
829 {
830  switch (d_proto->type()) {
831  case dods_byte_c:
832  case dods_char_c:
833  case dods_int8_c:
834  case dods_uint8_c:
835 
836  case dods_int16_c:
837  case dods_uint16_c:
838 
839  case dods_int32_c:
840  case dods_uint32_c:
841  case dods_float32_c:
842 
843  case dods_int64_c:
844  case dods_uint64_c:
845  case dods_float64_c:
846 
847  case dods_enum_c:
848  checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
849  break;
850 
851  case dods_str_c:
852  case dods_url_c:
853  for (int64_t i = 0, e = length(); i < e; ++i)
854  checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
855  break;
856 
857  case dods_opaque_c:
858  case dods_structure_c:
859  case dods_sequence_c:
860  d_proto->compute_checksum(checksum);
861  break;
862 
863  case dods_array_c: // No array of array
864  case dods_grid_c: // No grids in DAP4
865  default:
866  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
867  break;
868  }
869 }
870 
871 void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
872 {
873  if (!read_p())
874  read(); // read() throws Error and InternalErr
875 
876  switch (d_proto->type()) {
877  case dods_byte_c:
878  case dods_char_c:
879  case dods_int8_c:
880  case dods_uint8_c:
881  case dods_int16_c:
882  case dods_uint16_c:
883  case dods_int32_c:
884  case dods_uint32_c:
885  case dods_int64_c:
886  case dods_uint64_c:
887 
888  case dods_enum_c:
889 
890  case dods_float32_c:
891  case dods_float64_c:
892 
893  case dods_str_c:
894  case dods_url_c:
895 #if 0
896  compute_checksum(checksum);
897 #endif
898  break;
899 
900  case dods_opaque_c:
901  case dods_structure_c:
902  case dods_sequence_c:
903  // Modified the assert here from '... != 0' to '... >= length())
904  // to accommodate the case of a zero-length array. jhrg 1/28/16
905  assert(d_compound_buf.capacity() >= (unsigned)length());
906 
907  for (int i = 0, e = length(); i < e; ++i)
908  d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
909  break;
910 
911  case dods_array_c: // No Array of Array in DAP4 either...
912  case dods_grid_c:
913  default:
914  throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
915  break;
916  }
917 }
918 
919 void
920 Vector::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter /*= false*/)
921 {
922  if (!read_p())
923  read(); // read() throws Error and InternalErr
924 #if 0
925  if (filter && !eval.eval_selection(dmr, dataset()))
926  return true;
927 #endif
928  int64_t num = length(); // The constrained length in elements
929 
930  DBG(cerr << __PRETTY_FUNCTION__ << ", num: " << num << endl);
931 
932  // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
933  if (num == 0)
934  return;
935 
936  switch (d_proto->type()) {
937  case dods_byte_c:
938  case dods_char_c:
939  case dods_int8_c:
940  case dods_uint8_c:
941  m.put_vector(d_buf, num);
942  break;
943 
944  case dods_int16_c:
945  case dods_uint16_c:
946  case dods_int32_c:
947  case dods_uint32_c:
948  case dods_int64_c:
949  case dods_uint64_c:
950  m.put_vector(d_buf, num, d_proto->width());
951  break;
952 
953  case dods_enum_c:
954  if (d_proto->width() == 1)
955  m.put_vector(d_buf, num);
956  else
957  m.put_vector(d_buf, num, d_proto->width());
958  break;
959 
960  case dods_float32_c:
961  m.put_vector_float32(d_buf, num);
962  break;
963 
964  case dods_float64_c:
965  m.put_vector_float64(d_buf, num);
966  break;
967 
968  case dods_str_c:
969  case dods_url_c:
970  assert((int64_t)d_str.capacity() >= num);
971 
972  for (int64_t i = 0; i < num; ++i)
973  m.put_str(d_str[i]);
974 
975  break;
976 
977  case dods_array_c:
978  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
979 
980  case dods_opaque_c:
981  case dods_structure_c:
982  case dods_sequence_c:
983  assert(d_compound_buf.capacity() >= 0);
984 
985  for (int64_t i = 0; i < num; ++i)
986  d_compound_buf[i]->serialize(m, dmr, /*eval,*/ filter);
987 
988  break;
989 
990  case dods_grid_c:
991  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
992 
993  default:
994  throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
995  break;
996  }
997 
998 #ifdef CLEAR_LOCAL_DATA
1000 #endif
1001 }
1002 
1003 void
1005 {
1006  if (m_is_cardinal_type()) {
1007  if (d_buf)
1009  if (!d_buf)
1011  }
1012 
1013  DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1014 
1015  // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1016  if (length() == 0)
1017  return;
1018 
1019  switch (d_proto->type()) {
1020  case dods_byte_c:
1021  case dods_char_c:
1022  case dods_int8_c:
1023  case dods_uint8_c:
1024  um.get_vector((char *)d_buf, length());
1025  break;
1026 
1027  case dods_int16_c:
1028  case dods_uint16_c:
1029  case dods_int32_c:
1030  case dods_uint32_c:
1031  case dods_int64_c:
1032  case dods_uint64_c:
1033  um.get_vector((char *)d_buf, length(), d_proto->width());
1034  break;
1035 
1036  case dods_enum_c:
1037  if (d_proto->width() == 1)
1038  um.get_vector((char *)d_buf, length());
1039  else
1040  um.get_vector((char *)d_buf, length(), d_proto->width());
1041  break;
1042 
1043  case dods_float32_c:
1044  um.get_vector_float32((char *)d_buf, length());
1045  break;
1046 
1047  case dods_float64_c:
1048  um.get_vector_float64((char *)d_buf, length());
1049  break;
1050 
1051  case dods_str_c:
1052  case dods_url_c: {
1053  int64_t len = length();
1054  d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1055  d_capacity = len; // capacity is number of strings we can fit.
1056 
1057  for (int64_t i = 0; i < len; ++i) {
1058  um.get_str(d_str[i]);
1059  }
1060 
1061  break;
1062  }
1063 
1064  case dods_array_c:
1065  throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1066 
1067  case dods_opaque_c:
1068  case dods_structure_c:
1069  case dods_sequence_c: {
1070  vec_resize(length());
1071 
1072  for (int64_t i = 0, end = length(); i < end; ++i) {
1073  d_compound_buf[i] = d_proto->ptr_duplicate();
1074  d_compound_buf[i]->deserialize(um, dmr);
1075  }
1076 
1077  break;
1078  }
1079 
1080  case dods_grid_c:
1081  throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1082 
1083  default:
1084  throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1085  break;
1086  }
1087 }
1088 
1116 unsigned int Vector::val2buf(void *val, bool reuse)
1117 {
1118  // Jose Garcia
1119 
1120  // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1121  if (!val && length() == 0)
1122  return 0;
1123 
1124  // I *think* this method has been mainly designed to be use by read which
1125  // is implemented in the surrogate library. Passing NULL as a pointer to
1126  // this method will be an error of the creator of the surrogate library.
1127  // Even though I recognize the fact that some methods inside libdap++ can
1128  // call val2buf, I think by now no coding bugs such as misusing val2buf
1129  // will be in libdap++, so it will be an internal error from the
1130  // surrogate library.
1131  if (!val)
1132  throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1133 
1134  switch (d_proto->type()) {
1135  case dods_byte_c:
1136  case dods_char_c:
1137  case dods_int8_c:
1138  case dods_uint8_c:
1139  case dods_int16_c:
1140  case dods_uint16_c:
1141  case dods_int32_c:
1142  case dods_uint32_c:
1143  case dods_int64_c:
1144  case dods_uint64_c:
1145 
1146  case dods_enum_c:
1147 
1148  case dods_float32_c:
1149  case dods_float64_c:
1150 #if 0
1151  if (d_buf && !reuse)
1153 #endif
1154  // First time or no reuse (free'd above)
1155  if (!d_buf || !reuse)
1157 
1158  // width(true) returns the size in bytes given the constraint
1159  memcpy(d_buf, val, width(true));
1160  break;
1161 
1162  case dods_str_c:
1163  case dods_url_c:
1164  // Assume val points to an array of C++ string objects. Copy
1165  // them into the vector<string> field of this object.
1166  // Note: d_length is the number of elements in the Vector
1167  d_str.resize(d_length);
1168  d_capacity = d_length;
1169  for (int i = 0; i < d_length; ++i)
1170  d_str[i] = *(static_cast<string *> (val) + i);
1171 
1172  break;
1173 
1174  default:
1175  throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1176 
1177  }
1178 
1179  return width(true);
1180 }
1181 
1212 unsigned int Vector::buf2val(void **val)
1213 {
1214  // Jose Garcia
1215  // The same comment in Vector::val2buf applies here!
1216  if (!val)
1217  throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1218 
1219  unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
1220 
1221  // This is the width computed using length(). The
1222  // length() property is changed when a projection
1223  // constraint is applied. Thus this is the number of
1224  // bytes in the buffer given the current constraint.
1225 
1226  switch (d_proto->type()) {
1227  case dods_byte_c:
1228  case dods_char_c:
1229  case dods_int8_c:
1230  case dods_uint8_c:
1231  case dods_int16_c:
1232  case dods_uint16_c:
1233  case dods_int32_c:
1234  case dods_uint32_c:
1235  case dods_int64_c:
1236  case dods_uint64_c:
1237 
1238  case dods_enum_c:
1239 
1240  case dods_float32_c:
1241  case dods_float64_c:
1242  if (!d_buf)
1243  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1244  if (!*val)
1245  *val = new char[wid];
1246 
1247  memcpy(*val, d_buf, wid);
1248  return wid;
1249  break;
1250 
1251  case dods_str_c:
1252  case dods_url_c: {
1253  if (d_str.empty())
1254  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1255  if (!*val)
1256  *val = new string[d_length];
1257 
1258  for (int i = 0; i < d_length; ++i)
1259  *(static_cast<string *> (*val) + i) = d_str[i];
1260 
1261  return width();
1262  break;
1263  }
1264 
1265  default:
1266  throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1267  }
1268 
1269  //return wid;
1270 }
1271 
1292 void Vector::set_vec(unsigned int i, BaseType * val)
1293 {
1295 }
1296 
1303 void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1304 {
1305  // Jose Garcia
1306  // This is a public method which allows users to set the elements
1307  // of *this* vector. Passing an invalid index, a NULL pointer or
1308  // mismatching the vector type are internal errors.
1309  if (i >= static_cast<unsigned int> (d_length))
1310  throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1311  if (!val)
1312  throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1313  if (val->type() != d_proto->type())
1314  throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1315 
1316  if (i >= d_compound_buf.capacity())
1317  vec_resize(i + 10);
1318 
1319  d_compound_buf[i] = val;
1320 }
1321 
1332 {
1333  if (d_buf) {
1334  delete[] d_buf;
1335  d_buf = 0;
1336  }
1337 
1338  for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1339  delete d_compound_buf[i];
1340  d_compound_buf[i] = 0;
1341  }
1342 
1343  // Force memory to be reclaimed.
1344  d_compound_buf.resize(0);
1345  d_str.resize(0);
1346 
1347  d_capacity = 0;
1348  set_read_p(false);
1349 }
1350 
1358 unsigned int Vector::get_value_capacity() const
1359 {
1360  return d_capacity;
1361 }
1362 
1372 void Vector::reserve_value_capacity(unsigned int numElements)
1373 {
1374  if (!d_proto) {
1375  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1376  }
1377  switch (d_proto->type()) {
1378  case dods_byte_c:
1379  case dods_char_c:
1380  case dods_int8_c:
1381  case dods_uint8_c:
1382  case dods_int16_c:
1383  case dods_uint16_c:
1384  case dods_int32_c:
1385  case dods_uint32_c:
1386  case dods_int64_c:
1387  case dods_uint64_c:
1388 
1389  case dods_enum_c:
1390 
1391  case dods_float32_c:
1392  case dods_float64_c:
1393  // Make _buf be the right size and set _capacity
1395  break;
1396 
1397  case dods_str_c:
1398  case dods_url_c:
1399  // Make sure the d_str has enough room for all the strings.
1400  // Technically not needed, but it will speed things up for large arrays.
1401  d_str.reserve(numElements);
1402  d_capacity = numElements;
1403  break;
1404 
1405  case dods_array_c:
1406  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1407  break;
1408 
1409  case dods_opaque_c:
1410  case dods_structure_c:
1411  case dods_sequence_c:
1412  case dods_grid_c:
1413  // not clear anyone will go this path, but best to be complete.
1414  d_compound_buf.reserve(numElements);
1415  d_capacity = numElements;
1416  break;
1417 
1418  default:
1419  throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1420  break;
1421 
1422  } // switch
1423 
1424 }
1425 
1432 {
1433  // Use the current length of the vector as the reserve amount.
1435 }
1436 
1465 unsigned int
1466 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
1467 {
1468  static const string funcName = "set_value_slice_from_row_major_vector:";
1469 
1470  // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1471  Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1472 
1473  bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1474  if (!typesMatch) {
1475  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1476  }
1477 
1478  // Make sure the data exists
1479  if (!rowMajorData.read_p()) {
1480  throw InternalErr(__FILE__, __LINE__,
1481  funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1482  }
1483 
1484  // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1485  if (rowMajorData.length() < 0) {
1486  throw InternalErr(__FILE__, __LINE__,
1487  funcName
1488  + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
1489  }
1490 
1491  // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1492  // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1493  if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
1494  throw InternalErr(__FILE__, __LINE__,
1495  funcName
1496  + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1497  }
1498 
1499  // Make sure there's enough room in this Vector to store all the elements requested. Again,
1500  // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1501  if (d_capacity < (startElement + rowMajorData.length())) {
1502  throw InternalErr(__FILE__, __LINE__,
1503  funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1504  }
1505 
1506  // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1507  switch (d_proto->type()) {
1508  case dods_int8_c:
1509  case dods_uint8_c:
1510  case dods_byte_c:
1511  case dods_char_c:
1512  case dods_int16_c:
1513  case dods_uint16_c:
1514  case dods_int32_c:
1515  case dods_uint32_c:
1516  case dods_int64_c:
1517  case dods_uint64_c:
1518 
1519  case dods_enum_c:
1520 
1521  case dods_float32_c:
1522  case dods_float64_c: {
1523  if (!d_buf) {
1524  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1525  }
1526  if (!rowMajorData.d_buf) {
1527  throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1528  }
1529  // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1530  int varWidth = d_proto->width();
1531  char* pFromBuf = rowMajorData.d_buf;
1532  int numBytesToCopy = rowMajorData.width(true);
1533  char* pIntoBuf = d_buf + (startElement * varWidth);
1534  memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1535  break;
1536  }
1537 
1538  case dods_str_c:
1539  case dods_url_c:
1540  // Strings need to be copied directly
1541  for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
1542  d_str[startElement + i] = rowMajorData.d_str[i];
1543  }
1544  break;
1545 
1546  case dods_array_c:
1547  case dods_opaque_c:
1548  case dods_structure_c:
1549  case dods_sequence_c:
1550  case dods_grid_c:
1551  // Not sure that this function will be used for these type of nested objects, so I will throw here.
1552  throw InternalErr(__FILE__, __LINE__,
1553  funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1554  break;
1555 
1556  default:
1557  throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1558  break;
1559 
1560  } // switch (_var->type())
1561 
1562  // This is how many elements we copied.
1563  return (unsigned int) rowMajorData.length();
1564 }
1565 
1574 template <typename T>
1575 static bool types_match(Type t, T *cpp_var)
1576 {
1577  switch (t) {
1578  case dods_byte_c:
1579  case dods_char_c:
1580  case dods_uint8_c:
1581  return typeid(cpp_var) == typeid(dods_byte*);
1582 
1583  case dods_int8_c:
1584  return typeid(cpp_var) == typeid(dods_int8*);
1585  case dods_int16_c:
1586  return typeid(cpp_var) == typeid(dods_int16*);
1587  case dods_uint16_c:
1588  return typeid(cpp_var) == typeid(dods_uint16*);
1589  case dods_int32_c:
1590  return typeid(cpp_var) == typeid(dods_int32*);
1591  case dods_uint32_c:
1592  return typeid(cpp_var) == typeid(dods_uint32*);
1593  case dods_int64_c:
1594  return typeid(cpp_var) == typeid(dods_int64*);
1595  case dods_uint64_c:
1596  return typeid(cpp_var) == typeid(dods_uint64*);
1597 
1598  case dods_float32_c:
1599  return typeid(cpp_var) == typeid(dods_float32*);
1600  case dods_float64_c:
1601  return typeid(cpp_var) == typeid(dods_float64*);
1602 
1603  case dods_null_c:
1604  case dods_enum_c:
1605  case dods_str_c:
1606  case dods_url_c:
1607  case dods_opaque_c:
1608  case dods_array_c:
1609  case dods_structure_c:
1610  case dods_sequence_c:
1611  case dods_group_c:
1612  default:
1613  return false;
1614  }
1615 }
1616 
1618 
1620 template <typename T>
1621 bool Vector::set_value_worker(T *v, int sz)
1622 {
1623  if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1624  return false;
1625 
1627  return true;
1628 }
1629 
1630 bool Vector::set_value(dods_byte *val, int sz)
1631 {
1632  return set_value_worker(val, sz);
1633 }
1634 bool Vector::set_value(dods_int8 *val, int sz)
1635 {
1636  return set_value_worker(val, sz);
1637 }
1638 bool Vector::set_value(dods_int16 *val, int sz)
1639 {
1640  return set_value_worker(val, sz);
1641 }
1642 bool Vector::set_value(dods_uint16 *val, int sz)
1643 {
1644  return set_value_worker(val, sz);
1645 }
1646 bool Vector::set_value(dods_int32 *val, int sz)
1647 {
1648  return set_value_worker(val, sz);
1649 }
1650 bool Vector::set_value(dods_uint32 *val, int sz)
1651 {
1652  return set_value_worker(val, sz);
1653 }
1654 bool Vector::set_value(dods_int64 *val, int sz)
1655 {
1656  return set_value_worker(val, sz);
1657 }
1658 bool Vector::set_value(dods_uint64 *val, int sz)
1659 {
1660  return set_value_worker(val, sz);
1661 }
1662 bool Vector::set_value(dods_float32 *val, int sz)
1663 {
1664  return set_value_worker(val, sz);
1665 }
1666 bool Vector::set_value(dods_float64 *val, int sz)
1667 {
1668  return set_value_worker(val, sz);
1669 }
1670 
1672 bool Vector::set_value(string *val, int sz)
1673 {
1674  if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
1675  d_str.resize(sz);
1676  d_capacity = sz;
1677  for (register int t = 0; t < sz; t++) {
1678  d_str[t] = val[t];
1679  }
1680  set_length(sz);
1681  set_read_p(true);
1682  return true;
1683  }
1684  else {
1685  return false;
1686  }
1687 }
1688 
1689 template<typename T>
1690 bool Vector::set_value_worker(vector<T> &v, int sz)
1691 {
1692  return set_value(&v[0], sz);
1693 }
1694 
1695 bool Vector::set_value(vector<dods_byte> &val, int sz)
1696 {
1697  return set_value_worker(val, sz);
1698 }
1699 bool Vector::set_value(vector<dods_int8> &val, int sz)
1700 {
1701  return set_value_worker(val, sz);
1702 }
1703 bool Vector::set_value(vector<dods_int16> &val, int sz)
1704 {
1705  return set_value_worker(val, sz);
1706 }
1707 bool Vector::set_value(vector<dods_uint16> &val, int sz)
1708 {
1709  return set_value_worker(val, sz);
1710 }
1711 bool Vector::set_value(vector<dods_int32> &val, int sz)
1712 {
1713  return set_value_worker(val, sz);
1714 }
1715 bool Vector::set_value(vector<dods_uint32> &val, int sz)
1716 {
1717  return set_value_worker(val, sz);
1718 }
1719 bool Vector::set_value(vector<dods_int64> &val, int sz)
1720 {
1721  return set_value_worker(val, sz);
1722 }
1723 bool Vector::set_value(vector<dods_uint64> &val, int sz)
1724 {
1725  return set_value_worker(val, sz);
1726 }
1727 bool Vector::set_value(vector<dods_float32> &val, int sz)
1728 {
1729  return set_value_worker(val, sz);
1730 }
1731 bool Vector::set_value(vector<dods_float64> &val, int sz)
1732 {
1733  return set_value_worker(val, sz);
1734 }
1735 
1736 
1738 bool Vector::set_value(vector<string> &val, int sz)
1739 {
1740  if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
1741  d_str.resize(sz);
1742  d_capacity = sz;
1743  for (register int t = 0; t < sz; t++) {
1744  d_str[t] = val[t];
1745  }
1746  set_length(sz);
1747  set_read_p(true);
1748  return true;
1749  }
1750  else {
1751  return false;
1752  }
1753 }
1755 
1757 
1774 template <typename T>
1775 void Vector::value_worker(vector<unsigned int> *indices, T *b) const
1776 {
1777  // unsigned long currentIndex;
1778 #if 0
1779  // Iterator version. Not tested, jhrg 8/14/13
1780  for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
1781  unsigned long currentIndex = *i;
1782  if(currentIndex > (unsigned int)length()){
1783  stringstream s;
1784  s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
1785  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1786  throw Error(s.str());
1787  }
1788  b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
1789  }
1790 #endif
1791  for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
1792  unsigned long currentIndex = (*indices)[i];
1793  if (currentIndex > (unsigned int)length()) {
1794  stringstream s;
1795  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1796  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1797  throw Error(s.str());
1798  }
1799  b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
1800  }
1801 }
1802 void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
1803 void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
1804 void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
1805 void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
1806 void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
1807 void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
1808 void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
1809 void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
1810 void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
1811 void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
1812 
1813 #if 0
1814 template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
1815 template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
1816 template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
1817 template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
1818 template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
1819 template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
1820 template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
1821 template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
1822 template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
1823 template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
1824 #endif
1825 
1827 void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
1828 {
1829  unsigned long currentIndex;
1830 
1831  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
1832  for(unsigned long i=0; i<subsetIndex->size() ;++i){
1833  currentIndex = (*subsetIndex)[i] ;
1834  if(currentIndex > (unsigned int)length()){
1835  stringstream s;
1836  s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
1837  "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
1838  throw Error(s.str());
1839  }
1840  b[i] = d_str[currentIndex];
1841  }
1842  }
1843 }
1844 
1845 template <typename T>
1846 void Vector::value_worker(T *v) const
1847 {
1848  // Only copy if v is not null and the proto's type matches.
1849  // For Enums, use the element type since type == dods_enum_c.
1850  if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
1851  memcpy(v, d_buf, length() * sizeof(T));
1852 }
1853 void Vector::value(dods_byte *b) const { value_worker(b); }
1854 void Vector::value(dods_int8 *b) const { value_worker(b); }
1855 void Vector::value(dods_int16 *b) const { value_worker(b); }
1856 void Vector::value(dods_uint16 *b) const { value_worker(b); }
1857 void Vector::value(dods_int32 *b) const { value_worker(b); }
1858 void Vector::value(dods_uint32 *b) const { value_worker(b); }
1859 void Vector::value(dods_int64 *b) const { value_worker(b); }
1860 void Vector::value(dods_uint64 *b) const { value_worker(b); }
1861 void Vector::value(dods_float32 *b) const { value_worker(b); }
1862 void Vector::value(dods_float64 *b) const { value_worker(b); }
1863 
1864 #if 0
1865 template void Vector::value(dods_byte *v) const;
1866 template void Vector::value(dods_int8 *v) const;
1867 template void Vector::value(dods_int16 *v) const;
1868 template void Vector::value(dods_uint16 *v) const;
1869 template void Vector::value(dods_int32 *v) const;
1870 template void Vector::value(dods_uint32 *v) const;
1871 template void Vector::value(dods_int64 *v) const;
1872 template void Vector::value(dods_uint64 *v) const;
1873 template void Vector::value(dods_float32 *v) const;
1874 template void Vector::value(dods_float64 *v) const;
1875 #endif
1876 
1877 
1879 void Vector::value(vector<string> &b) const
1880 {
1881  if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
1882  b = d_str;
1883 }
1884 
1888 {
1889  void *buffer = new char[width(true)];
1890 
1891  memcpy(buffer, d_buf, width(true));
1892 
1893  return buffer;
1894 }
1896 
1913 {
1914 #if 0
1915  // Why doesn't this work? tried all 3 variants. jhrg 8/14/13
1916  Vector::add_var_nocopy(v->ptr_duplicate(), p);
1917  add_var_nocopy(v->ptr_duplicate(), p);
1918  add_var_nocopy(v->ptr_duplicate());
1919 #else
1920  // Delete the current template variable
1921  if (d_proto) {
1922  delete d_proto;
1923  d_proto = 0;
1924  }
1925 
1926  // if 'v' is null, just set _var to null and exit.
1927  if (!v) {
1928  d_proto = 0;
1929  }
1930  else {
1931  // Jose Garcia
1932  // By getting a copy of this object to be assigned to _var
1933  // we let the owner of 'v' to deallocate it as necessary.
1934  d_proto = v->ptr_duplicate();
1935 
1936  // If 'v' has a name, use it as the name of the array. If v doesn't have
1937  // a name, then make sure to copy the array's name to it
1938  // so that software which uses the template's name will still work.
1939  if (!v->name().empty())
1940  set_name(v->name());
1941  else
1942  d_proto->set_name(name());
1943 
1944  d_proto->set_parent(this); // Vector --> child
1945 
1946  DBG(cerr << "Vector::add_var: Added variable " << v << " ("
1947  << v->name() << " " << v->type_name() << ")" << endl);
1948  }
1949 #endif
1950 }
1951 
1952 void Vector::add_var_nocopy(BaseType * v, Part)
1953 {
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  d_proto = v;
1966 
1967  // If 'v' has a name, use it as the name of the array. If it *is*
1968  // empty, then make sure to copy the array's name to the template
1969  // so that software which uses the template's name will still work.
1970  if (!v->name().empty())
1971  set_name(v->name());
1972  else
1973  d_proto->set_name(name());
1974 
1975  d_proto->set_parent(this); // Vector is the parent; proto is the child
1976 
1977  DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
1978  << v->name() << " " << v->type_name() << ")" << endl);
1979  }
1980 }
1981 
1982 bool Vector::check_semantics(string & msg, bool)
1983 {
1984  return BaseType::check_semantics(msg);
1985 }
1986 
1995 void Vector::dump(ostream &strm) const
1996 {
1997  strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
1998  DapIndent::Indent();
1999  BaseType::dump(strm);
2000  strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2001  if (d_proto) {
2002  strm << DapIndent::LMarg << "base type:" << endl;
2003  DapIndent::Indent();
2004  d_proto->dump(strm);
2005  DapIndent::UnIndent();
2006  }
2007  else {
2008  strm << DapIndent::LMarg << "base type: not set" << endl;
2009  }
2010  strm << DapIndent::LMarg << "vector contents:" << endl;
2011  DapIndent::Indent();
2012  for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2013  if (d_compound_buf[i])
2014  d_compound_buf[i]->dump(strm);
2015  else
2016  strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2017  }
2018  DapIndent::UnIndent();
2019  strm << DapIndent::LMarg << "strings:" << endl;
2020  DapIndent::Indent();
2021  for (unsigned i = 0; i < d_str.size(); i++) {
2022  strm << DapIndent::LMarg << d_str[i] << endl;
2023  }
2024  DapIndent::UnIndent();
2025  if (d_buf) {
2026  switch (d_proto != 0 ? d_proto->type() : 0) {
2027  case dods_byte_c:
2028  case dods_char_c:
2029  strm << DapIndent::LMarg << "_buf: ";
2030  strm.write(d_buf, d_length);
2031  strm << endl;
2032  break;
2033 
2034  case 0:
2035  default:
2036  strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2037  break;
2038  }
2039  }
2040  else {
2041  strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2042  }
2043 
2044  DapIndent::UnIndent();
2045 }
2046 
2047 } // namespace libdap
2048 
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:820
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:425
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:54
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:1198
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1358
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1292
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:289
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:80
virtual void dump(ostream &strm) const
dumps information about this object
Definition: Vector.cc:1995
virtual void intern_data()
Read data into this variable.
Definition: Vector.cc:871
virtual void clear_local_data()
Definition: Vector.cc:1331
Read data from the stream made by D4StreamMarshaller.
virtual int length() const
Definition: Vector.cc:515
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:828
virtual void set_read_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:367
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:1912
virtual int element_count(bool leaves)
Count the members of constructor types.
Definition: Vector.cc:334
virtual void * value()
Definition: Vector.cc:1887
void m_set_cardinal_values_internal(const CardType *fromArray, int numElts)
Definition: Vector.cc:220
virtual unsigned int set_value_slice_from_row_major_vector(const Vector &rowMajorData, unsigned int startElement)
Definition: Vector.cc:1466
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 Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:310
virtual bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true)
Serialize a Vector.
Definition: Vector.cc:627
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:654
A class for software fault reporting.
Definition: InternalErr.h:64
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:303
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=0)
Definition: Vector.cc:392
virtual bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false)
Receive data from the net.
Definition: Vector.cc:727
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:679
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 string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:324
Holds a DAP4 enumeration.
Definition: D4Enum.h:61
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:357
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:388
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:513
void set_vec_nocopy(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1303
virtual void dump(ostream &strm) const
dumps information about this object
Definition: BaseType.cc:236
bool m_is_cardinal_type() const
Definition: Vector.cc:124
virtual void reserve_value_capacity()
Definition: Vector.cc:1431
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:461
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition: Vector.cc:249
virtual unsigned int val2buf(void *val, bool reuse=false)
Reads data into the Vector buffer. Thrown if called for Structure, Sequence or Grid.
Definition: Vector.cc:1116
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:1982
void m_delete_cardinal_data_buffer()
Definition: Vector.cc:209
void AddData(const uint8_t *pData, const uint32_t length)
Definition: crc.h:98
virtual unsigned int val2buf(void *val, bool reuse=false)=0
Loads class data.
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:265
virtual BaseType * ptr_duplicate()=0
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
Evaluate a constraint expression.
virtual void set_send_p(bool state)
Indicates that the data is ready to send.
Definition: Vector.cc:355
unsigned int m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
Definition: Vector.cc:181
virtual void put_vector(char *val, int64_t num_bytes)
Write a fixed size vector.
The basic data type for the DODS DAP types.
Definition: BaseType.h:117
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
virtual void set_name(const std::string &name)
Sets the name of the class instance.
Definition: Vector.cc:324
virtual unsigned int buf2val(void **val)
Definition: Vector.cc:1212
bool eval_selection(DDS &dds, const std::string &dataset)
Evaluate a boolean-valued constraint expression. This is main method for the evaluator ans is called ...
virtual void set_length(int l)
Definition: Vector.cc:522
A class for error processing.
Definition: Error.h:90
virtual void put_vector_float64(char *val, int64_t num_elem)
Write a fixed size vector of float64s.
void vec_resize(int l)
Definition: Vector.cc:535
virtual unsigned int width(bool constrained=false) const
Returns the width of the data, in bytes.
Definition: Vector.cc:503
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:1130