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