libdap Updated for version 3.21.0
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#include <cstdint>
41
42#include <sstream>
43#include <vector>
44#include <algorithm>
45#include <typeinfo>
46
47#include "crc.h"
48
49#include "Vector.h"
50#include "Marshaller.h"
51#include "UnMarshaller.h"
52
53#include "D4StreamMarshaller.h"
54#include "D4StreamUnMarshaller.h"
55
56#include "D4Enum.h"
57
58#include "Type.h"
59#include "dods-datatypes.h"
60#include "dods-limits.h"
61#include "escaping.h"
62#include "debug.h"
63#include "InternalErr.h"
64#include "DapIndent.h"
65
66#undef CLEAR_LOCAL_DATA
67
68using std::cerr;
69using std::endl;
70
71namespace libdap {
72
73void Vector::m_duplicate(const Vector & v)
74{
75 d_length = v.d_length;
76 d_length_ll = v.d_length_ll;
77
78 // _var holds the type of the elements. That is, it holds a BaseType
79 // which acts as a template for the type of each element.
80 if (v.d_proto) {
81 // Vector manages this ptr, delete before assigning a new object. jhrg 2/19/22
82 if (d_proto) delete 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 = nullptr;
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 d_capacity_ll = v.d_capacity_ll;
120}
121
126bool Vector::m_is_cardinal_type() const
127{
128 // Not cardinal if no d_proto at all!
129 if (!d_proto) {
130 return false;
131 }
132
133 switch (d_proto->type()) {
134 case dods_byte_c:
135 case dods_char_c:
136 case dods_int16_c:
137 case dods_uint16_c:
138 case dods_int32_c:
139 case dods_uint32_c:
140 case dods_float32_c:
141 case dods_float64_c:
142 // New cardinal types for DAP4
143 case dods_int8_c:
144 case dods_uint8_c:
145 case dods_int64_c:
146 case dods_uint64_c:
147
148 case dods_enum_c:
149 return true;
150
151 // These must be handled differently.
152 case dods_str_c:
153 case dods_url_c:
154 case dods_opaque_c:
155
156 case dods_array_c:
157
158 case dods_structure_c:
159 case dods_sequence_c:
160 case dods_grid_c:
161 return false;
162
163 default:
164 assert("Vector::var: Unrecognized type");
165 return false;
166 }
167}
168
181int64_t Vector::m_create_cardinal_data_buffer_for_type(int64_t num_elements)
182{
183 // Make sure we HAVE a _var, or we cannot continue.
184 if (!d_proto) {
185 throw InternalErr(__FILE__, __LINE__,
186 "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
187 }
188
189 // Make sure we only do this for the correct data types.
190 if (!m_is_cardinal_type()) {
191 throw InternalErr(__FILE__, __LINE__,
192 "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
193 }
194
195 // Handle this special case where this is an array that holds no values
196 if (num_elements == 0)
197 return 0;
198
199 m_delete_cardinal_data_buffer();
200
201 // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
202#if 0
203 unsigned int bytesPerElt = d_proto->width();
204 unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
205#endif
206 int64_t bytesNeeded = d_proto->width_ll() * num_elements;
207 d_buf = new char[bytesNeeded];
208
209#if 0
210 d_capacity = (unsigned long long)num_elements;
211#endif
212 set_value_capacity((uint64_t)num_elements);
213 return bytesNeeded;
214}
215
217void Vector::m_delete_cardinal_data_buffer()
218{
219 delete[] d_buf;
220 d_buf = nullptr;
221 d_capacity = 0;
222 d_capacity_ll = 0;
223}
224
228template<class CardType>
229void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int64_t numElts)
230{
231 if (numElts < 0) {
232 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
233 }
234 if (!fromArray) {
235 throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
236 }
237 set_length_ll(numElts);
238 m_create_cardinal_data_buffer_for_type(numElts);
239 if (d_buf)
240 memcpy(d_buf, fromArray, numElts * sizeof(CardType));
241 set_read_p(true);
242}
243
259Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
260 BaseType(n, t, is_dap4)
261{
262 if (v)
263 add_var(v);
264
265 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
266 if (d_proto)
267 d_proto->set_parent(this);
268}
269
288Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
289 BaseType(n, d, t, is_dap4)
290{
291 if (v)
292 add_var(v);
293
294 DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
295 if (d_proto)
296 d_proto->set_parent(this);
297}
298
300Vector::Vector(const Vector & rhs) : BaseType(rhs)
301
302{
303 DBG2(cerr << "Entering Vector const ctor for object: " << this <<
304 endl); DBG2(cerr << "RHS: " << &rhs << endl);
305
306 m_duplicate(rhs);
307}
308
309Vector::~Vector()
310{
311 delete d_proto;
312 d_proto = nullptr;
313
314 // Clears all buffers
315 try {
317 }
318 catch (const std::exception &) {
319 // It's hard to know what to do - Log it when we can, but that can fail, too.
320 }
321}
322
323Vector & Vector::operator=(const Vector & rhs)
324{
325 if (this == &rhs)
326 return *this;
327 BaseType::operator=(rhs);
328 m_duplicate(rhs);
329 return *this;
330}
331
332void Vector::set_name(const std::string& name)
333{
335 // We need to set the prototype name as well since
336 // this is what gets output in the dds! Otherwise, there's a mismatch.
337 if (d_proto) {
338 d_proto->set_name(name);
339 }
340}
341
342int Vector::element_count(bool leaves)
343{
344 if (!leaves)
345 return 1;
346 else
347 return d_proto->element_count(leaves);
348 // var() only works for simple types!
349 // jhrg 8/19/13 return var(0)->element_count(leaves);
350}
351
352// These mfuncs set the _send_p and _read_p fields of BaseType. They differ
353// from BaseType's version in that they set both the Vector object's copy of
354// _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
355// is a scalar, but does matter when it is an aggregate.
356
363void Vector::set_send_p(bool state)
364{
365 if (d_proto) {
366 d_proto->set_send_p(state);
367
368 // because some code may depend on the BaseType*s held in d_compound_buf
369 // behaving as if they are 'ordinary' DAP variables, make sure their send_p
370 // flag is set if they exist. Because space in the vector is allocated
371 // before values (BaseType*s) are added, check for nulls and limit the
372 // iteration to only those elements actually in the object including any
373 // constraints that may have been applied - these are values not declarations.
374 // jhrg 5/13/16
375 switch (d_proto->type()) {
376 case dods_structure_c:
377 case dods_sequence_c:
378 case dods_grid_c:
379 if (d_compound_buf.size() > 0) {
380 for (unsigned long long i = 0; i < (unsigned) d_length; ++i) {
381 if (d_compound_buf[i]) d_compound_buf[i]->set_send_p(state);
382 }
383 }
384 break;
385
386 default:
387 break;
388 }
389 }
390
392}
393
400void Vector::set_read_p(bool state)
401{
402 if (d_proto) {
403 d_proto->set_read_p(state);
404
405 // See comment above.
406 switch (d_proto->type()) {
407 case dods_structure_c:
408 case dods_sequence_c:
409 case dods_grid_c:
410 if (d_compound_buf.size() > 0) {
411 for (unsigned long long i = 0; i < (unsigned)d_length; ++i) {
412 if (d_compound_buf[i]) d_compound_buf[i]->set_read_p(state);
413 }
414 }
415 break;
416
417 default:
418 break;
419 }
420 }
421
423}
424
434void Vector::set_length(int64_t l)
435{
437}
438
447{
448 d_length_ll = l;
449 if (l <= DODS_INT_MAX)
450 d_length = (int)l;
451 else {
452 d_length = -1;
453 d_too_big_for_dap2 = true;
454 }
455}
456
457void Vector::set_value_capacity(uint64_t l)
458{
459 d_capacity_ll = l;
460 if (l <= DODS_UINT_MAX)
461 d_capacity = (unsigned int)l;
462 else {
463 d_capacity = 0;
464 d_too_big_for_dap2 = true;
465 }
466}
467
468
486BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
487{
488 string name = www2id(n);
489 DBG2(cerr << "Vector::var: Looking for " << name << endl);
490
491 if (name.empty() || d_proto->name() == name) {
492 if (s)
493 s->push(this);
494 return d_proto;
495 }
496
497 // If this is a Vector of constructor types, look for 'name' recursively.
498 // Make sure to check for the case where name is the default (the empty
499 // string). 9/1/98 jhrg
500 if (d_proto->is_constructor_type()) {
501 BaseType *result = d_proto->var(name, exact, s);
502 if (result && s)
503 s->push(this);
504 return result;
505 }
506
507 return NULL;
508}
509
520BaseType *Vector::var(const string & n, btp_stack & s)
521{
522 string name = www2id(n);
523
524 if (d_proto->is_constructor_type())
525 return d_proto->var(name, s);
526 else {
527 s.push((BaseType *) this);
528 return d_proto;
529 }
530}
531
543#if 0
544BaseType *Vector::var(unsigned int i)
545{
546 switch (d_proto->type()) {
547 case dods_byte_c:
548 case dods_char_c:
549 case dods_int8_c:
550 case dods_uint8_c:
551 case dods_int16_c:
552 case dods_uint16_c:
553 case dods_int32_c:
554 case dods_uint32_c:
555 case dods_int64_c:
556 case dods_uint64_c:
557
558 case dods_enum_c:
559
560 case dods_float32_c:
561 case dods_float64_c:
562 // Transfer the ith value to the BaseType *d_proto
563 d_proto->val2buf(d_buf + (i * (uint64_t)d_proto->width_ll()));
564 return d_proto;
565
566 case dods_str_c:
567 case dods_url_c:
568 d_proto->val2buf(&d_str[i]);
569 return d_proto;
570
571 case dods_opaque_c:
572 case dods_array_c:
573 case dods_structure_c:
574 case dods_sequence_c:
575 case dods_grid_c:
576 return d_compound_buf[i];
577
578 default:
579 throw Error ("Vector::var: Unrecognized type");
580 }
581}
582#endif
583
584BaseType *Vector::var(unsigned int i)
585{
586 return var_ll(i);
587}
588
589BaseType *Vector::var_ll(uint64_t i)
590{
591 switch (d_proto->type()) {
592 case dods_byte_c:
593 case dods_char_c:
594 case dods_int8_c:
595 case dods_uint8_c:
596 case dods_int16_c:
597 case dods_uint16_c:
598 case dods_int32_c:
599 case dods_uint32_c:
600 case dods_int64_c:
601 case dods_uint64_c:
602
603 case dods_enum_c:
604
605 case dods_float32_c:
606 case dods_float64_c:
607 // Transfer the ith value to the BaseType *d_proto
608 d_proto->val2buf(d_buf + (i * (uint64_t)d_proto->width_ll()));
609 return d_proto;
610
611 case dods_str_c:
612 case dods_url_c:
613 d_proto->val2buf(&d_str[i]);
614 return d_proto;
615
616 case dods_opaque_c:
617 case dods_array_c:
618 case dods_structure_c:
619 case dods_sequence_c:
620 case dods_grid_c:
621 return d_compound_buf[i];
622
623 default:
624 throw Error ("Vector::var: Unrecognized type");
625 }
626}
627
628
638{
639 // I added this check, which alters the behavior of the method. jhrg 8/14/13
640 if (m_is_cardinal_type())
641 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
642
643 // Use resize() since other parts of the code use operator[]. Note that size() should
644 // be used when resize() is used. Using capacity() creates problems as noted in the
645 // comment in set_vec_nocopy(). jhrg 5/19/17
646 d_compound_buf.resize(l, 0); // Fill with NULLs
647#if 0
648 d_capacity = d_compound_buf.size(); // size in terms of number of elements.
649#endif
650 set_value_capacity(d_compound_buf.size());
651
652}
653
654void Vector::vec_resize_ll(int64_t l)
655{
656 // I added this check, which alters the behavior of the method. jhrg 8/14/13
657 if (m_is_cardinal_type())
658 throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
659
660 // Use resize() since other parts of the code use operator[]. Note that size() should
661 // be used when resize() is used. Using capacity() creates problems as noted in the
662 // comment in set_vec_nocopy(). jhrg 5/19/17
663 d_compound_buf.resize(l, nullptr); // Fill with NULLs
664#if 0
665 d_capacity = d_compound_buf.size(); // size in terms of number of elements.
666#endif
667 set_value_capacity(d_compound_buf.size());
668
669}
687{
688 DBG(cerr << "Vector::intern_data: " << name() << endl);
689 if (is_dap4())
690 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (").append(name()).append(")."), __FILE__, __LINE__);
691
692 if (!read_p())
693 read(); // read() throws Error and InternalErr
694
695 // length() is not capacity; it must be set explicitly in read().
696 int num = length();
697
698 switch (d_proto->type()) {
699 case dods_byte_c:
700 case dods_int16_c:
701 case dods_uint16_c:
702 case dods_int32_c:
703 case dods_uint32_c:
704 case dods_float32_c:
705 case dods_float64_c:
706 // For these cases, read() puts the data into d_buf,
707 // which is what we need.
708 break;
709
710 case dods_str_c:
711 case dods_url_c:
712 // For these cases, read() will put the data into d_str[],
713 // which is also what we need.
714 break;
715
716 case dods_array_c:
717 // This is an error since there can never be an Array of Array.
718 throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
719
720 case dods_structure_c:
721 case dods_sequence_c:
722 case dods_grid_c:
723 DBG(cerr << "Vector::intern_data: found ctor" << endl);
724 // For these cases, we need to call read() for each of the 'num'
725 // elements in the 'd_compound_buf[]' array of BaseType object pointers.
726 //
727 // I changed the test here from '... = 0' to '... < num' to accommodate
728 // the case where the array is zero-length.
729 if (d_compound_buf.capacity() < (unsigned)num)
730 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
731
732 for (int i = 0; i < num; ++i)
733 d_compound_buf[i]->intern_data(eval, dds);
734
735 break;
736
737 default:
738 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
739 }
740}
741
752bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
753{
754 // Add protection against calling this with DAP4 types. Technically not needed,
755 // but the 'Unknown Datatype' message is not very useful. jhrg 7/28/22
756 if (is_dap4())
757 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (").append(name()).append(")."), __FILE__, __LINE__);
758
759 if (d_too_big_for_dap2)
760 throw Error("Trying to send a variable that is too large for DAP2.", __FILE__, __LINE__);
761
762 // Added to streamline zero-length arrays. Not needed for correct function,
763 // but explicitly handling this case here makes the code easier to follow.
764 // In libdap::Vector::val2buf() there is a test that will catch the zero-length
765 // case as well. We still need to call serialize since it will write size
766 // information that the client depends on. jhrg 2/17/16
767 if (length() == 0)
768 set_read_p(true);
769 else if (!read_p())
770 read(); // read() throws Error and InternalErr
771
772 if (ce_eval && !eval.eval_selection(dds, dataset()))
773 return true;
774
775 // length() is not capacity; it must be set explicitly in read().
776 int num = length();
777
778 bool status = false;
779
780 switch (d_proto->type()) {
781 case dods_byte_c:
782 m.put_vector(d_buf, num, *this);
783 status = true;
784 break;
785
786 case dods_int16_c:
787 case dods_uint16_c:
788 case dods_int32_c:
789 case dods_uint32_c:
790 case dods_float32_c:
791 case dods_float64_c:
792 assert((int)d_proto->width_ll() == d_proto->width_ll());
793 m.put_vector(d_buf, num, (int)d_proto->width_ll(), *this);
794 status = true;
795
796 break;
797
798 case dods_str_c:
799 case dods_url_c:
800 if (d_str.capacity() == 0)
801 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
802
803 m.put_int(num);
804
805 for (int i = 0; i < num; ++i)
806 m.put_str(d_str[i]);
807
808 status = true;
809 break;
810
811 case dods_array_c:
812 case dods_structure_c:
813 case dods_sequence_c:
814 case dods_grid_c:
815 //Jose Garcia
816 // Not setting the capacity of d_compound_buf is an internal error.
817 if (d_compound_buf.capacity() == 0)
818 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
819
820 m.put_int(num);
821 status = true;
822 for (int i = 0; i < num && status; ++i)
823 status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
824
825 break;
826
827 default:
828 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
829 }
830
831#ifdef CLEAR_LOCAL_DATA
833#endif
834
835 return status;
836}
837
838// Read an object from the network and internalize it. For a Vector this is
839// handled differently for a `cardinal' type. Vectors of Cardinals are
840// stored using the `C' representations because these objects often are used
841// to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
842// arrays of non-cardinal types are stored as Vectors of the C++ objects or
843// DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
844// Grid are vectors of the libdap Structure, ... classes).
845//
846// The boolean parameter REUSE determines whether internal storage is reused
847// or not. If true, the _buf member is assumed to be large enough to hold the
848// incoming cardinal data and is *not* reallocated. If false, new storage is
849// allocated. If the internal buffer has not yet been allocated, then this
850// parameter has no effect (i.e., storage is allocated). This parameter
851// effects storage for cardinal data only.
852//
853// Returns: True is successful, false otherwise.
854
855bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
856{
857 unsigned int num;
858 unsigned i = 0;
859
860 if (is_dap4())
861 throw Error(string("A method usable only with DAP2 variables was called on a DAP4 variable (").append(name()).append(")."), __FILE__, __LINE__);
862
863 switch (d_proto->type()) {
864 case dods_byte_c:
865 case dods_int16_c:
866 case dods_uint16_c:
867 case dods_int32_c:
868 case dods_uint32_c:
869 case dods_float32_c:
870 case dods_float64_c:
871 um.get_int((int &) num);
872
873 DBG(cerr << "Vector::deserialize: num = " << num << endl);
874 DBG(cerr << "Vector::deserialize: length = " << length() << endl);
875
876 if (length() == -1)
877 set_length(num);
878
879 if (num != (unsigned int) length())
880 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
881
882 if (!d_buf || !reuse) {
883 // Make d_buf be large enough for length_ll() elements of _var->type()
884 // m_create...() deletes the old buffer.
885 m_create_cardinal_data_buffer_for_type(length_ll());
886 }
887
888 // Added to accommodate zero-length arrays.
889 // Note that the rest of the cases will just send the size without data
890 // but that these calls trigger error testing in the UnMarshaller code.
891 // jhrg 1/28/16
892 if (num == 0)
893 return true;
894
895 if (d_proto->type() == dods_byte_c)
896 um.get_vector((char **) &d_buf, num, *this);
897 else {
898 assert((int)d_proto->width_ll() == d_proto->width_ll());
899 um.get_vector((char **) &d_buf, num, d_proto->width_ll(), *this);
900 }
901 break;
902
903 case dods_str_c:
904 case dods_url_c:
905 um.get_int((int &) num);
906
907 if (length() == -1)
908 set_length(num);
909
910 if (num != (unsigned int) length())
911 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
912
913 d_str.resize((num > 0) ? num : 0); // Fill with NULLs
914#if 0
915 d_capacity = num; // capacity is number of strings we can fit.
916#endif
917 set_value_capacity((uint64_t)num);
918
919 for (i = 0; i < num; ++i) {
920 string str;
921 um.get_str(str);
922 d_str[i] = str;
923 }
924
925 break;
926
927 case dods_array_c:
928 // Added jhrg 5/18/17
929 // This replaces a comment that was simply 'TO DO'
930 throw InternalErr(__FILE__, __LINE__, "Array of array!");
931
932 case dods_structure_c:
933 case dods_sequence_c:
934 case dods_grid_c:
935 um.get_int((int &) num);
936
937 if (length() == -1)
938 set_length(num);
939
940 if (num != (unsigned int) length())
941 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
942
943 vec_resize(num);
944
945 for (i = 0; i < num; ++i) {
946 d_compound_buf[i] = d_proto->ptr_duplicate();
947 d_compound_buf[i]->deserialize(um, dds);
948 }
949
950 break;
951
952 default:
953 throw InternalErr(__FILE__, __LINE__, "Unknown type!");
954 }
955
956 return false;
957}
958
960{
961 switch (d_proto->type()) {
962 case dods_byte_c:
963 case dods_char_c:
964 case dods_int8_c:
965 case dods_uint8_c:
966
967 case dods_int16_c:
968 case dods_uint16_c:
969
970 case dods_int32_c:
971 case dods_uint32_c:
972 case dods_float32_c:
973
974 case dods_int64_c:
975 case dods_uint64_c:
976 case dods_float64_c:
977
978 case dods_enum_c:
979 checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length_ll() * d_proto->width_ll());
980 break;
981
982 case dods_str_c:
983 case dods_url_c:
984 for (int64_t i = 0, e = length(); i < e; ++i)
985 checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].size());
986 break;
987
988 case dods_opaque_c:
989 case dods_structure_c:
990 case dods_sequence_c:
991 d_proto->compute_checksum(checksum);
992 break;
993
994 case dods_array_c: // No array of array
995 case dods_grid_c: // No grids in DAP4
996 default:
997 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
998 }
999}
1000
1001void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
1002{
1003 if (!read_p())
1004 read(); // read() throws Error and InternalErr
1005
1006 switch (d_proto->type()) {
1007 case dods_byte_c:
1008 case dods_char_c:
1009 case dods_int8_c:
1010 case dods_uint8_c:
1011 case dods_int16_c:
1012 case dods_uint16_c:
1013 case dods_int32_c:
1014 case dods_uint32_c:
1015 case dods_int64_c:
1016 case dods_uint64_c:
1017
1018 case dods_enum_c:
1019
1020 case dods_float32_c:
1021 case dods_float64_c:
1022
1023 case dods_str_c:
1024 case dods_url_c:
1025#if 0
1026 compute_checksum(checksum);
1027#endif
1028 break;
1029
1030 case dods_opaque_c:
1031 case dods_structure_c:
1032 case dods_sequence_c:
1033 // Modified the assertion here from '... != 0' to '... >= length())
1034 // to accommodate the case of a zero-length array. jhrg 1/28/16
1035 assert(d_compound_buf.capacity() >= (unsigned)length());
1036
1037 for (int i = 0, e = length(); i < e; ++i)
1038 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
1039 break;
1040
1041 case dods_array_c: // No Array of Array in DAP4 either...
1042 case dods_grid_c:
1043 default:
1044 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
1045 }
1046}
1047
1048void
1049Vector::serialize(D4StreamMarshaller &m, DMR &dmr, bool filter /*= false*/)
1050{
1051 if (!read_p())
1052 read(); // read() throws Error and InternalErr
1053#if 0
1054 if (filter && !eval.eval_selection(dmr, dataset()))
1055 return true;
1056#endif
1057 int64_t num = length_ll(); // The constrained length in elements
1058
1059 DBG(cerr << __func__ << ", num: " << num << endl);
1060
1061 // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
1062 if (num == 0)
1063 return;
1064
1065 switch (d_proto->type()) {
1066 case dods_byte_c:
1067 case dods_char_c:
1068 case dods_int8_c:
1069 case dods_uint8_c:
1070 m.put_vector(d_buf, num);
1071 break;
1072
1073 case dods_int16_c:
1074 case dods_uint16_c:
1075 case dods_int32_c:
1076 case dods_uint32_c:
1077 case dods_int64_c:
1078 case dods_uint64_c:
1079 m.put_vector(d_buf, num, (int)d_proto->width_ll());
1080 break;
1081
1082 case dods_enum_c:
1083 if (d_proto->width_ll() == 1)
1084 m.put_vector(d_buf, num);
1085 else
1086 m.put_vector(d_buf, num, (int)d_proto->width_ll());
1087 break;
1088
1089 case dods_float32_c:
1090 m.put_vector_float32(d_buf, num);
1091 break;
1092
1093 case dods_float64_c:
1094 m.put_vector_float64(d_buf, num);
1095 break;
1096
1097 case dods_str_c:
1098 case dods_url_c:
1099 assert((int64_t)d_str.capacity() >= num);
1100
1101 for (int64_t i = 0; i < num; ++i)
1102 m.put_str(d_str[i]);
1103
1104 break;
1105
1106 case dods_array_c:
1107 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1108
1109 case dods_opaque_c:
1110 case dods_structure_c:
1111 case dods_sequence_c:
1112 assert(d_compound_buf.capacity() >= 0);
1113
1114 for (int64_t i = 0; i < num; ++i) {
1115 DBG(cerr << __func__ << "d_compound_buf[" << i << "] " << d_compound_buf[i] << endl);
1116 d_compound_buf[i]->serialize(m, dmr, filter);
1117 }
1118
1119 break;
1120
1121 case dods_grid_c:
1122 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1123
1124 default:
1125 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
1126 }
1127
1128#ifdef CLEAR_LOCAL_DATA
1130#endif
1131}
1132
1133void
1135{
1136 if (m_is_cardinal_type()) {
1137 if (d_buf)
1138 m_delete_cardinal_data_buffer();
1139 if (!d_buf)
1140 m_create_cardinal_data_buffer_for_type(length());
1141 }
1142
1143 DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
1144
1145 // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
1146 if (length() == 0)
1147 return;
1148
1149 switch (d_proto->type()) {
1150 case dods_byte_c:
1151 case dods_char_c:
1152 case dods_int8_c:
1153 case dods_uint8_c:
1154 um.get_vector((char *)d_buf, length_ll());
1155 break;
1156
1157 case dods_int16_c:
1158 case dods_uint16_c:
1159 case dods_int32_c:
1160 case dods_uint32_c:
1161 case dods_int64_c:
1162 case dods_uint64_c:
1163 um.get_vector((char *)d_buf, length_ll(), d_proto->width_ll());
1164 break;
1165
1166 case dods_enum_c:
1167 if (d_proto->width_ll() == 1)
1168 um.get_vector((char *)d_buf, length_ll());
1169 else
1170 um.get_vector((char *)d_buf, length_ll(), d_proto->width_ll());
1171 break;
1172
1173 case dods_float32_c:
1174 um.get_vector_float32((char *)d_buf, length_ll());
1175 break;
1176
1177 case dods_float64_c:
1178 um.get_vector_float64((char *)d_buf, length_ll());
1179 break;
1180
1181 case dods_str_c:
1182 case dods_url_c: {
1183 int64_t len = length_ll();
1184 d_str.resize((len > 0) ? len : 0); // Fill with NULLs
1185 if (len < 0)
1186 throw InternalErr(__FILE__,__LINE__,"The number of string length is less than 0 ");
1187#if 0
1188 d_capacity = len; // capacity is number of strings we can fit.
1189#endif
1190 set_value_capacity(len);
1191 for (int64_t i = 0; i < len; ++i) {
1192 um.get_str(d_str[i]);
1193 }
1194
1195 break;
1196 }
1197
1198 case dods_array_c:
1199 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
1200
1201 case dods_opaque_c:
1202 case dods_structure_c:
1203 case dods_sequence_c: {
1204 vec_resize(length());
1205
1206 for (int64_t i = 0, end = length(); i < end; ++i) {
1207 d_compound_buf[i] = d_proto->ptr_duplicate();
1208 d_compound_buf[i]->deserialize(um, dmr);
1209 }
1210
1211 break;
1212 }
1213
1214 case dods_grid_c:
1215 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
1216
1217 default:
1218 throw InternalErr(__FILE__, __LINE__, "Unknown type.");
1219 }
1220}
1221
1249#if 0
1250unsigned int Vector::val2buf(void *val, bool reuse)
1251{
1252 // Jose Garcia
1253
1254 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1255 if (!val && length() == 0)
1256 return 0;
1257
1258 // I *think* this method has been mainly designed to be use by read which
1259 // is implemented in the surrogate library. Passing NULL as a pointer to
1260 // this method will be an error of the creator of the surrogate library.
1261 // Even though I recognize the fact that some methods inside libdap++ can
1262 // call val2buf, I think by now no coding bugs such as misusing val2buf
1263 // will be in libdap++, so it will be an internal error from the
1264 // surrogate library.
1265 if (!val)
1266 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1267
1268 switch (d_proto->type()) {
1269 case dods_byte_c:
1270 case dods_char_c:
1271 case dods_int8_c:
1272 case dods_uint8_c:
1273 case dods_int16_c:
1274 case dods_uint16_c:
1275 case dods_int32_c:
1276 case dods_uint32_c:
1277 case dods_int64_c:
1278 case dods_uint64_c:
1279
1280 case dods_enum_c:
1281
1282 case dods_float32_c:
1283 case dods_float64_c:
1284#if 0
1285 if (d_buf && !reuse)
1286 m_delete_cardinal_data_buffer();
1287#endif
1288 // First time or no reuse (free'd above)
1289 if (!d_buf || !reuse)
1290 m_create_cardinal_data_buffer_for_type(length_ll());
1291
1292 // width_ll(true) returns the size in bytes given the constraint
1293 if (d_buf)
1294 memcpy(d_buf, val, (uint64_t)width_ll(true));
1295 break;
1296
1297 case dods_str_c:
1298 case dods_url_c:
1299 {
1300 // Assume val points to an array of C++ string objects. Copy
1301 // them into the vector<string> field of this object.
1302 // Note: d_length is the number of elements in the Vector
1303#if 0
1304 d_str.resize(d_length);
1305 d_capacity = d_length;
1306 for (int i = 0; i < d_length; ++i)
1307 d_str[i] = *(static_cast<string *> (val) + i);
1308#endif
1309 int64_t str_len = length_ll();
1310 if (str_len <0)
1311 throw InternalErr(__FILE__,__LINE__,"The number of string length is less than 0 ");
1312 d_str.resize(str_len);
1313 set_value_capacity(str_len);
1314 for (int64_t i = 0; i < str_len; ++i)
1315 d_str[i] = *(static_cast<string *> (val) + i);
1316 }
1317
1318 break;
1319
1320 default:
1321 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1322
1323 }
1324
1325 return (unsigned int)width_ll(true);
1326}
1327#endif
1328
1329unsigned int Vector::val2buf(void *val, bool reuse) {
1330
1331 auto ret_value = (unsigned int) val2buf_ll(val,reuse);
1332 return ret_value;
1333}
1334
1335uint64_t Vector::val2buf_ll(void *val, bool reuse)
1336{
1337 // Jose Garcia
1338
1339 // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
1340 if (!val && length() == 0)
1341 return 0;
1342
1343 // I *think* this method has been mainly designed to be use by read which
1344 // is implemented in the surrogate library. Passing NULL as a pointer to
1345 // this method will be an error of the creator of the surrogate library.
1346 // Even though I recognize the fact that some methods inside libdap++ can
1347 // call val2buf, I think by now no coding bugs such as misusing val2buf
1348 // will be in libdap++, so it will be an internal error from the
1349 // surrogate library.
1350 if (!val)
1351 throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
1352
1353 switch (d_proto->type()) {
1354 case dods_byte_c:
1355 case dods_char_c:
1356 case dods_int8_c:
1357 case dods_uint8_c:
1358 case dods_int16_c:
1359 case dods_uint16_c:
1360 case dods_int32_c:
1361 case dods_uint32_c:
1362 case dods_int64_c:
1363 case dods_uint64_c:
1364
1365 case dods_enum_c:
1366
1367 case dods_float32_c:
1368 case dods_float64_c:
1369#if 0
1370 if (d_buf && !reuse)
1371 m_delete_cardinal_data_buffer();
1372#endif
1373 // First time or no reuse (free'd above)
1374 if (!d_buf || !reuse)
1375 m_create_cardinal_data_buffer_for_type(length_ll());
1376
1377 // width_ll(true) returns the size in bytes given the constraint
1378 if (d_buf)
1379 memcpy(d_buf, val, (uint64_t)width_ll(true));
1380 break;
1381
1382 case dods_str_c:
1383 case dods_url_c:
1384 {
1385 // Assume val points to an array of C++ string objects. Copy
1386 // them into the vector<string> field of this object.
1387 // Note: d_length is the number of elements in the Vector
1388#if 0
1389 d_str.resize(d_length);
1390 d_capacity = d_length;
1391 for (int i = 0; i < d_length; ++i)
1392 d_str[i] = *(static_cast<string *> (val) + i);
1393#endif
1394 int64_t str_len = length_ll();
1395 if (str_len <0)
1396 throw InternalErr(__FILE__,__LINE__,"The number of string length is less than 0 ");
1397 d_str.resize(str_len);
1398 set_value_capacity(str_len);
1399 for (int64_t i = 0; i < str_len; ++i)
1400 d_str[i] = *(static_cast<string *> (val) + i);
1401 }
1402
1403 break;
1404
1405 default:
1406 throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
1407
1408 }
1409
1410 return (unsigned int)width_ll(true);
1411}
1412
1413
1452unsigned int Vector::buf2val(void **val)
1453{
1454 // Jose Garcia
1455 // The same comment in Vector::val2buf applies here!
1456 if (!val)
1457 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1458
1459 int64_t wid = width_ll(true /* constrained */);
1460
1461 // This is the width computed using length(). The
1462 // length() property is changed when a projection
1463 // constraint is applied. Thus, this is the number of
1464 // bytes in the buffer given the current constraint.
1465
1466 switch (d_proto->type()) {
1467 case dods_byte_c:
1468 case dods_char_c:
1469 case dods_int8_c:
1470 case dods_uint8_c:
1471 case dods_int16_c:
1472 case dods_uint16_c:
1473 case dods_int32_c:
1474 case dods_uint32_c:
1475 case dods_int64_c:
1476 case dods_uint64_c:
1477
1478 case dods_enum_c:
1479
1480 case dods_float32_c:
1481 case dods_float64_c:
1482 if (!d_buf)
1483 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1484 if (!*val)
1485 *val = new char[wid];
1486
1487 memcpy(*val, d_buf, (uint64_t)wid);
1488 return (unsigned int)wid;
1489
1490 case dods_str_c:
1491 case dods_url_c: {
1492 if (d_str.empty())
1493 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1494 if (!*val)
1495 *val = new string[d_length];
1496
1497 for (int i = 0; i < d_length; ++i)
1498 *(static_cast<string *> (*val) + i) = d_str[i];
1499
1500 return (unsigned int)width_ll();
1501 }
1502
1503 default:
1504 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1505 }
1506}
1507
1508uint64_t Vector::buf2val_ll(void **val)
1509{
1510 // Jose Garcia
1511 // The same comment in Vector::val2buf applies here!
1512 if (!val)
1513 throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
1514
1515 int64_t wid = width_ll(true /* constrained */);
1516
1517 // This is the width computed using length(). The
1518 // length() property is changed when a projection
1519 // constraint is applied. Thus, this is the number of
1520 // bytes in the buffer given the current constraint.
1521
1522 switch (d_proto->type()) {
1523 case dods_byte_c:
1524 case dods_char_c:
1525 case dods_int8_c:
1526 case dods_uint8_c:
1527 case dods_int16_c:
1528 case dods_uint16_c:
1529 case dods_int32_c:
1530 case dods_uint32_c:
1531 case dods_int64_c:
1532 case dods_uint64_c:
1533
1534 case dods_enum_c:
1535
1536 case dods_float32_c:
1537 case dods_float64_c:
1538 if (!d_buf)
1539 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
1540 if (!*val)
1541 *val = new char[wid];
1542
1543 memcpy(*val, d_buf, (uint64_t)wid);
1544 return (uint64_t)wid;
1545
1546 case dods_str_c:
1547 case dods_url_c: {
1548 if (d_str.empty())
1549 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
1550 if (!*val)
1551 *val = new string[d_length_ll];
1552
1553 for (int64_t i = 0; i < d_length_ll; ++i)
1554 *(static_cast<string *> (*val) + i) = d_str[i];
1555
1556 return (uint64_t)width_ll();
1557 }
1558
1559 default:
1560 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
1561 }
1562}
1563
1564
1585void Vector::set_vec(unsigned int i, BaseType * val)
1586{
1588}
1589
1590void Vector::set_vec_ll(uint64_t i, BaseType * val)
1591{
1592 Vector::set_vec_nocopy_ll(i, val->ptr_duplicate());
1593}
1594
1606void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
1607{
1608 // Jose Garcia
1609 // This is a public method which allows users to set the elements
1610 // of *this* vector. Passing an invalid index, a NULL pointer or
1611 // mismatching the vector type are internal errors.
1612 if (i >= static_cast<unsigned int> (d_length))
1613 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1614 if (!val)
1615 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1616 if (val->type() != d_proto->type())
1617 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1618
1619 // This code originally used capacity() instead of size(), but that was an error.
1620 // Use capacity() when using reserve() and size() when using resize(). Mixing
1621 // capacity() with resize() leaves holes in the data, where (pointer) values are
1622 // filled with nulls during successive calls to resize(). The resize() heuristic
1623 // remembers previous calls on a given vector<> and allocates larger than requested
1624 // blocks of memory on successive calls, which has the strange affect of erasing
1625 // values already in the vector in the parts just added.
1626 // jhrg 5/18/17
1627 if (i >= d_compound_buf.size()) {
1628 vec_resize(d_compound_buf.size() + 100);
1629 }
1630
1631 d_compound_buf[i] = val;
1632}
1633
1634void Vector::set_vec_nocopy_ll(uint64_t i, BaseType * val)
1635{
1636 // Jose Garcia
1637 // This is a public method which allows users to set the elements
1638 // of *this* vector. Passing an invalid index, a NULL pointer or
1639 // mismatching the vector type are internal errors.
1640 if (i >= static_cast<uint64_t> (length_ll()))
1641 throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
1642 if (!val)
1643 throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
1644 if (val->type() != d_proto->type())
1645 throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
1646
1647 // This code originally used capacity() instead of size(), but that was an error.
1648 // Use capacity() when using reserve() and size() when using resize(). Mixing
1649 // capacity() with resize() leaves holes in the data, where (pointer) values are
1650 // filled with nulls during successive calls to resize(). The resize() heuristic
1651 // remembers previous calls on a given vector<> and allocates larger than requested
1652 // blocks of memory on successive calls, which has the strange affect of erasing
1653 // values already in the vector in the parts just added.
1654 // jhrg 5/18/17
1655 if (i >= d_compound_buf.size()) {
1656 vec_resize_ll(d_compound_buf.size() + 100);
1657 }
1658
1659 d_compound_buf[i] = val;
1660}
1661
1662
1673{
1674 if (d_buf) {
1675 delete[] d_buf;
1676 d_buf = 0;
1677 }
1678
1679 for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
1680 delete d_compound_buf[i];
1681 d_compound_buf[i] = 0;
1682 }
1683
1684 // Force memory to be reclaimed.
1685 d_compound_buf.resize(0);
1686 d_str.resize(0);
1687
1688 d_capacity = 0;
1689 d_capacity_ll = 0;
1690 set_read_p(false);
1691}
1692
1700unsigned int Vector::get_value_capacity() const
1701{
1702 return d_capacity;
1703}
1704
1705uint64_t Vector::get_value_capacity_ll() const
1706{
1707 return d_capacity_ll;
1708}
1718void Vector::reserve_value_capacity(unsigned int numElements)
1719{
1720 if (!d_proto) {
1721 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1722 }
1723 switch (d_proto->type()) {
1724 case dods_byte_c:
1725 case dods_char_c:
1726 case dods_int8_c:
1727 case dods_uint8_c:
1728 case dods_int16_c:
1729 case dods_uint16_c:
1730 case dods_int32_c:
1731 case dods_uint32_c:
1732 case dods_int64_c:
1733 case dods_uint64_c:
1734
1735 case dods_enum_c:
1736
1737 case dods_float32_c:
1738 case dods_float64_c:
1739 // Make _buf be the right size and set _capacity
1740 m_create_cardinal_data_buffer_for_type(numElements);
1741 break;
1742
1743 case dods_str_c:
1744 case dods_url_c:
1745 // Make sure the d_str has enough room for all the strings.
1746 // Technically not needed, but it will speed things up for large arrays.
1747 d_str.reserve(numElements);
1748#if 0
1749 d_capacity = numElements;
1750#endif
1751 set_value_capacity(numElements);
1752 break;
1753
1754 case dods_array_c:
1755 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1756
1757 case dods_opaque_c:
1758 case dods_structure_c:
1759 case dods_sequence_c:
1760 case dods_grid_c:
1761 // not clear anyone will go this path, but best to be complete.
1762 d_compound_buf.reserve(numElements);
1763#if 0
1764 d_capacity = numElements;
1765#endif
1766 set_value_capacity(numElements);
1767 break;
1768
1769 default:
1770 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1771 } // switch
1772
1773}
1774
1781{
1782 // Use the current length of the vector as the reserve amount.
1784}
1794void Vector::reserve_value_capacity_ll(uint64_t numElements)
1795{
1796 if (!d_proto) {
1797 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
1798 }
1799 switch (d_proto->type()) {
1800 case dods_byte_c:
1801 case dods_char_c:
1802 case dods_int8_c:
1803 case dods_uint8_c:
1804 case dods_int16_c:
1805 case dods_uint16_c:
1806 case dods_int32_c:
1807 case dods_uint32_c:
1808 case dods_int64_c:
1809 case dods_uint64_c:
1810
1811 case dods_enum_c:
1812
1813 case dods_float32_c:
1814 case dods_float64_c:
1815 // Make _buf be the right size and set _capacity
1816 m_create_cardinal_data_buffer_for_type(numElements);
1817 break;
1818
1819 case dods_str_c:
1820 case dods_url_c:
1821 // Make sure the d_str has enough room for all the strings.
1822 // Technically not needed, but it will speed things up for large arrays.
1823 d_str.reserve(numElements);
1824#if 0
1825 d_capacity = numElements;
1826#endif
1827 set_value_capacity(numElements);
1828 break;
1829
1830 case dods_array_c:
1831 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
1832
1833 case dods_opaque_c:
1834 case dods_structure_c:
1835 case dods_sequence_c:
1836 case dods_grid_c:
1837 // not clear anyone will go this path, but best to be complete.
1838 d_compound_buf.reserve(numElements);
1839#if 0
1840 d_capacity = numElements;
1841#endif
1842 set_value_capacity(numElements);
1843 break;
1844
1845 default:
1846 throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
1847 } // switch
1848
1849}
1850
1857{
1858 // Use the current length of the vector as the reserve amount.
1860}
1861
1868
1869 d_buf = new char[numBytes];
1870
1871}
1900uint64_t
1901Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, uint64_t startElement)
1902{
1903 static const string funcName = "set_value_slice_from_row_major_vector:";
1904
1905 // semantically const from the caller's viewpoint, but some calls are not syntactic const.
1906 Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
1907
1908 bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
1909 if (!typesMatch) {
1910 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
1911 }
1912
1913 // Make sure the data exists
1914 if (!rowMajorData.read_p()) {
1915 throw InternalErr(__FILE__, __LINE__,
1916 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
1917 }
1918
1919 // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
1920 if (rowMajorData.length_ll() < 0) {
1921 throw InternalErr(__FILE__, __LINE__,
1922 funcName
1923 + "Logic error: the Vector to copy data from has length_ll() < 0 and was probably not initialized!");
1924 }
1925
1926 // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
1927 // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
1928 if (rowMajorData.get_value_capacity_ll() < static_cast<uint64_t>(rowMajorData.length_ll())) {
1929 throw InternalErr(__FILE__, __LINE__,
1930 funcName
1931 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
1932 }
1933
1934 // Make sure there's enough room in this Vector to store all the elements requested. Again,
1935 // better to throw than just copy what we can since it implies a logic error that needs to be solved.
1936 if (d_capacity_ll < (startElement + rowMajorData.length_ll())) {
1937 throw InternalErr(__FILE__, __LINE__,
1938 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
1939 }
1940
1941 // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
1942 switch (d_proto->type()) {
1943 case dods_int8_c:
1944 case dods_uint8_c:
1945 case dods_byte_c:
1946 case dods_char_c:
1947 case dods_int16_c:
1948 case dods_uint16_c:
1949 case dods_int32_c:
1950 case dods_uint32_c:
1951 case dods_int64_c:
1952 case dods_uint64_c:
1953
1954 case dods_enum_c:
1955
1956 case dods_float32_c:
1957 case dods_float64_c: {
1958 if (!d_buf) {
1959 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
1960 }
1961 if (!rowMajorData.d_buf) {
1962 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
1963 }
1964 // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
1965 int64_t varWidth = d_proto->width_ll();
1966 char* pFromBuf = rowMajorData.d_buf;
1967 int64_t numBytesToCopy = rowMajorData.width_ll(true);
1968 char* pIntoBuf = d_buf + (startElement * varWidth);
1969 memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
1970 break;
1971 }
1972
1973 case dods_str_c:
1974 case dods_url_c:
1975 // Strings need to be copied directly
1976 for (uint64_t i = 0; i < static_cast<uint64_t>(rowMajorData.length_ll()); ++i) {
1977 d_str[startElement + i] = rowMajorData.d_str[i];
1978 }
1979 break;
1980
1981 case dods_array_c:
1982 case dods_opaque_c:
1983 case dods_structure_c:
1984 case dods_sequence_c:
1985 case dods_grid_c:
1986 // Not sure that this function will be used for these type of nested objects, so I will throw here.
1987 throw InternalErr(__FILE__, __LINE__,
1988 funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
1989
1990 default:
1991 throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
1992 } // switch (_var->type())
1993
1994 // This is how many elements we copied.
1995 return (uint64_t) rowMajorData.length_ll();
1996}
1997
2006template <typename T>
2007static bool types_match(Type t, T *cpp_var)
2008{
2009 switch (t) {
2010 case dods_byte_c:
2011 case dods_char_c:
2012 case dods_uint8_c:
2013 return typeid(cpp_var) == typeid(dods_byte*);
2014
2015 case dods_int8_c:
2016 return typeid(cpp_var) == typeid(dods_int8*);
2017 case dods_int16_c:
2018 return typeid(cpp_var) == typeid(dods_int16*);
2019 case dods_uint16_c:
2020 return typeid(cpp_var) == typeid(dods_uint16*);
2021 case dods_int32_c:
2022 return typeid(cpp_var) == typeid(dods_int32*);
2023 case dods_uint32_c:
2024 return typeid(cpp_var) == typeid(dods_uint32*);
2025 case dods_int64_c:
2026 return typeid(cpp_var) == typeid(dods_int64*);
2027 case dods_uint64_c:
2028 return typeid(cpp_var) == typeid(dods_uint64*);
2029
2030 case dods_float32_c:
2031 return typeid(cpp_var) == typeid(dods_float32*);
2032 case dods_float64_c:
2033 return typeid(cpp_var) == typeid(dods_float64*);
2034
2035 case dods_null_c:
2036 case dods_enum_c:
2037 case dods_str_c:
2038 case dods_url_c:
2039 case dods_opaque_c:
2040 case dods_array_c:
2041 case dods_structure_c:
2042 case dods_sequence_c:
2043 case dods_group_c:
2044 default:
2045 return false;
2046 }
2047}
2048
2050
2052template <typename T>
2053bool Vector::set_value_worker(T *v, int sz)
2054{
2055 if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
2056 return false;
2057 m_set_cardinal_values_internal(v, (int64_t)sz);
2058 return true;
2059}
2060
2061template <typename T>
2062bool Vector::set_value_ll_worker(T *v, int64_t sz)
2063{
2064 if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
2065 return false;
2066
2067 m_set_cardinal_values_internal(v, sz);
2068 return true;
2069}
2070
2071
2072bool Vector::set_value(dods_byte *val, int sz)
2073{
2074 return set_value_worker(val, sz);
2075}
2076
2077bool Vector::set_value(dods_int8 *val, int sz)
2078{
2079 return set_value_worker(val, sz);
2080}
2081bool Vector::set_value(dods_int16 *val, int sz)
2082{
2083 return set_value_worker(val, sz);
2084}
2085bool Vector::set_value(dods_uint16 *val, int sz)
2086{
2087 return set_value_worker(val, sz);
2088}
2089bool Vector::set_value(dods_int32 *val, int sz)
2090{
2091 return set_value_worker(val, sz);
2092}
2093bool Vector::set_value(dods_uint32 *val, int sz)
2094{
2095 return set_value_worker(val, sz);
2096}
2097bool Vector::set_value(dods_int64 *val, int sz)
2098{
2099 return set_value_worker(val, sz);
2100}
2101bool Vector::set_value(dods_uint64 *val, int sz)
2102{
2103 return set_value_worker(val, sz);
2104}
2105bool Vector::set_value(dods_float32 *val, int sz)
2106{
2107 return set_value_worker(val, sz);
2108}
2109bool Vector::set_value(dods_float64 *val, int sz)
2110{
2111 return set_value_worker(val, sz);
2112}
2113
2114bool Vector::set_value_ll(dods_byte *val, int64_t sz)
2115{
2116 return set_value_ll_worker(val, sz);
2117}
2118
2119bool Vector::set_value_ll(dods_int8 *val, int64_t sz)
2120{
2121 return set_value_ll_worker(val, sz);
2122}
2123bool Vector::set_value_ll(dods_int16 *val, int64_t sz)
2124{
2125 return set_value_ll_worker(val, sz);
2126}
2127bool Vector::set_value_ll(dods_uint16 *val, int64_t sz)
2128{
2129 return set_value_ll_worker(val, sz);
2130}
2131bool Vector::set_value_ll(dods_int32 *val, int64_t sz)
2132{
2133 return set_value_ll_worker(val, sz);
2134}
2135bool Vector::set_value_ll(dods_uint32 *val, int64_t sz)
2136{
2137 return set_value_ll_worker(val, sz);
2138}
2139bool Vector::set_value_ll(dods_int64 *val, int64_t sz)
2140{
2141 return set_value_ll_worker(val, sz);
2142}
2143bool Vector::set_value_ll(dods_uint64 *val, int64_t sz)
2144{
2145 return set_value_ll_worker(val, sz);
2146}
2147bool Vector::set_value_ll(dods_float32 *val, int64_t sz)
2148{
2149 return set_value_ll_worker(val, sz);
2150}
2151bool Vector::set_value_ll(dods_float64 *val, int64_t sz)
2152{
2153 return set_value_ll_worker(val, sz);
2154}
2155
2156
2164bool Vector::set_value(string *val, int sz)
2165{
2166 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
2167 d_str.resize(sz);
2168#if 0
2169 d_capacity = sz;
2170#endif
2171 set_value_capacity(sz);
2172 for (int t = 0; t < sz; t++) {
2173 d_str[t] = val[t];
2174 }
2175 set_length(sz);
2176 set_read_p(true);
2177 return true;
2178 }
2179 else {
2180 return false;
2181 }
2182}
2183
2184bool Vector::set_value_ll(string *val, int64_t sz)
2185{
2186 if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
2187 d_str.resize(sz);
2188#if 0
2189 d_capacity_ll = sz;
2190#endif
2191 set_value_capacity(sz);
2192 for (int64_t t = 0; t < sz; t++) {
2193 d_str[t] = val[t];
2194 }
2195 set_length_ll(sz);
2196 set_read_p(true);
2197 return true;
2198 }
2199 else {
2200 return false;
2201 }
2202}
2203
2204template<typename T>
2205bool Vector::set_value_worker(vector<T> &v, int sz)
2206{
2207 return set_value(v.data(), sz);
2208}
2209
2210template<typename T>
2211bool Vector::set_value_ll_worker(vector<T> &v, int64_t sz)
2212{
2213 return set_value_ll(v.data(), sz);
2214}
2215
2216
2217bool Vector::set_value(vector<dods_byte> &val, int sz)
2218{
2219 return set_value_worker(val, sz);
2220}
2221bool Vector::set_value(vector<dods_int8> &val, int sz)
2222{
2223 return set_value_worker(val, sz);
2224}
2225bool Vector::set_value(vector<dods_int16> &val, int sz)
2226{
2227 return set_value_worker(val, sz);
2228}
2229bool Vector::set_value(vector<dods_uint16> &val, int sz)
2230{
2231 return set_value_worker(val, sz);
2232}
2233bool Vector::set_value(vector<dods_int32> &val, int sz)
2234{
2235 return set_value_worker(val, sz);
2236}
2237bool Vector::set_value(vector<dods_uint32> &val, int sz)
2238{
2239 return set_value_worker(val, sz);
2240}
2241bool Vector::set_value(vector<dods_int64> &val, int sz)
2242{
2243 return set_value_worker(val, sz);
2244}
2245bool Vector::set_value(vector<dods_uint64> &val, int sz)
2246{
2247 return set_value_worker(val, sz);
2248}
2249bool Vector::set_value(vector<dods_float32> &val, int sz)
2250{
2251 return set_value_worker(val, sz);
2252}
2253bool Vector::set_value(vector<dods_float64> &val, int sz)
2254{
2255 return set_value_worker(val, sz);
2256}
2257
2258bool Vector::set_value_ll(vector<dods_byte> &val, int64_t sz)
2259{
2260 return set_value_ll_worker(val, sz);
2261}
2262bool Vector::set_value_ll(vector<dods_int8> &val, int64_t sz)
2263{
2264 return set_value_ll_worker(val, sz);
2265}
2266bool Vector::set_value_ll(vector<dods_int16> &val, int64_t sz)
2267{
2268 return set_value_ll_worker(val, sz);
2269}
2270bool Vector::set_value_ll(vector<dods_uint16> &val, int64_t sz)
2271{
2272 return set_value_ll_worker(val, sz);
2273}
2274bool Vector::set_value_ll(vector<dods_int32> &val, int64_t sz)
2275{
2276 return set_value_ll_worker(val, sz);
2277}
2278bool Vector::set_value_ll(vector<dods_uint32> &val, int64_t sz)
2279{
2280 return set_value_ll_worker(val, sz);
2281}
2282bool Vector::set_value_ll(vector<dods_int64> &val, int64_t sz)
2283{
2284 return set_value_ll_worker(val, sz);
2285}
2286bool Vector::set_value_ll(vector<dods_uint64> &val, int64_t sz)
2287{
2288 return set_value_ll_worker(val, sz);
2289}
2290bool Vector::set_value_ll(vector<dods_float32> &val, int64_t sz)
2291{
2292 return set_value_ll_worker(val, sz);
2293}
2294bool Vector::set_value_ll(vector<dods_float64> &val, int64_t sz)
2295{
2296 return set_value_ll_worker(val, sz);
2297}
2298
2299
2301bool Vector::set_value(vector<string> &val, int sz)
2302{
2303 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
2304 d_str.resize(sz);
2305 d_capacity = sz;
2306 for (int t = 0; t < sz; t++) {
2307 d_str[t] = val[t];
2308 }
2309 set_length(sz);
2310 set_read_p(true);
2311 return true;
2312 }
2313 else {
2314 return false;
2315 }
2316}
2317
2318bool Vector::set_value_ll(vector<string> &val, int64_t sz)
2319{
2320 if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
2321 d_str.resize(sz);
2322 d_capacity_ll = sz;
2323 for (int64_t t = 0; t < sz; t++) {
2324 d_str[t] = val[t];
2325 }
2326 set_length_ll(sz);
2327 set_read_p(true);
2328 return true;
2329 }
2330 else {
2331 return false;
2332 }
2333}
2334
2336
2338
2355template <typename T>
2356void Vector::value_worker(vector<unsigned int> *indices, T *b) const
2357{
2358#if 0
2359 // Iterator version. Not tested, jhrg 8/14/13
2360 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
2361 unsigned long currentIndex = *i;
2362 if(currentIndex > (unsigned int)length()){
2363 stringstream s;
2364 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
2365 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2366 throw Error(s.str());
2367 }
2368 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
2369 }
2370#endif
2371 for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
2372 unsigned long currentIndex = (*indices)[i];
2373 if (currentIndex > (unsigned int)length()) {
2374 stringstream s;
2375 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
2376 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2377 throw Error(s.str());
2378 }
2379 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
2380 }
2381}
2382
2383template <typename T>
2384void Vector::value_ll_worker(vector<uint64_t> *indices, T *b) const
2385{
2386#if 0
2387 // Iterator version. Not tested, jhrg 8/14/13
2388 for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
2389 unsigned long currentIndex = *i;
2390 if(currentIndex > (unsigned int)length()){
2391 stringstream s;
2392 s << "Vector::value() - Subset index[" << i - subsetIndex->begin() << "] = " << currentIndex << " references a value that is " <<
2393 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2394 throw Error(s.str());
2395 }
2396 b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
2397 }
2398#endif
2399 for (uint64_t i = 0, e = indices->size(); i < e; ++i) {
2400 uint64_t currentIndex = (*indices)[i];
2401 if (currentIndex > (uint64_t)length_ll()) {
2402 stringstream s;
2403 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
2404 "outside the bounds of the internal storage [ length_ll()= " << length_ll() << " ] name: '" << name() << "'. ";
2405 throw Error(s.str());
2406 }
2407 b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
2408 }
2409}
2410
2411void Vector::value(vector<unsigned int> *indices, dods_byte *b) const { value_worker(indices, b); }
2412void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const { value_worker(indices, b); }
2413void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const { value_worker(indices, b); }
2414void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const { value_worker(indices, b); }
2415void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const { value_worker(indices, b); }
2416void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const { value_worker(indices, b); }
2417void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const { value_worker(indices, b); }
2418void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const { value_worker(indices, b); }
2419void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
2420void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
2421
2422void Vector::value_ll(vector<uint64_t> *indices, dods_byte *b) const { value_ll_worker(indices, b); }
2423void Vector::value_ll(vector<uint64_t> *indices, dods_int8 *b) const { value_ll_worker(indices, b); }
2424void Vector::value_ll(vector<uint64_t> *indices, dods_int16 *b) const { value_ll_worker(indices, b); }
2425void Vector::value_ll(vector<uint64_t> *indices, dods_uint16 *b) const { value_ll_worker(indices, b); }
2426void Vector::value_ll(vector<uint64_t> *indices, dods_int32 *b) const { value_ll_worker(indices, b); }
2427void Vector::value_ll(vector<uint64_t> *indices, dods_uint32 *b) const { value_ll_worker(indices, b); }
2428void Vector::value_ll(vector<uint64_t> *indices, dods_int64 *b) const { value_ll_worker(indices, b); }
2429void Vector::value_ll(vector<uint64_t> *indices, dods_uint64 *b) const { value_ll_worker(indices, b); }
2430void Vector::value_ll(vector<uint64_t> *indices, dods_float32 *b) const { value_ll_worker(indices, b); }
2431void Vector::value_ll(vector<uint64_t> *indices, dods_float64 *b) const { value_ll_worker(indices, b); }
2432
2433
2434#if 0
2435template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
2436template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
2437template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
2438template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
2439template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
2440template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
2441template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
2442template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
2443template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
2444template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
2445#endif
2446
2448void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
2449{
2450 unsigned long currentIndex;
2451
2452 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
2453 for(unsigned long i=0; i<subsetIndex->size() ;++i){
2454 currentIndex = (*subsetIndex)[i] ;
2455 if(currentIndex > (unsigned int)length()){
2456 stringstream s;
2457 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
2458 "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
2459 throw Error(s.str());
2460 }
2461 b[i] = d_str[currentIndex];
2462 }
2463 }
2464}
2465
2466void Vector::value_ll(vector<uint64_t> *subsetIndex, vector<string> &b) const
2467{
2468 uint64_t currentIndex;
2469
2470 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
2471 for(uint64_t i=0; i<subsetIndex->size() ;++i){
2472 currentIndex = (*subsetIndex)[i] ;
2473 if(currentIndex > (uint64_t)length_ll()){
2474 stringstream s;
2475 s << "Vector::value() - Subset index[" << i << "] = " << currentIndex << " references a value that is " <<
2476 "outside the bounds of the internal storage [ length_ll()= " << length_ll() << " ] name: '" << name() << "'. ";
2477 throw Error(s.str());
2478 }
2479 b[i] = d_str[currentIndex];
2480 }
2481 }
2482}
2483
2484
2485template <typename T>
2486void Vector::value_worker(T *v) const
2487{
2488 // Only copy if v is not null and the proto's type matches.
2489 // For Enums, use the element type since type == dods_enum_c.
2490 if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
2491 memcpy(v, d_buf, length_ll() * sizeof(T));
2492}
2493void Vector::value(dods_byte *b) const { value_worker(b); }
2494void Vector::value(dods_int8 *b) const { value_worker(b); }
2495void Vector::value(dods_int16 *b) const { value_worker(b); }
2496void Vector::value(dods_uint16 *b) const { value_worker(b); }
2497void Vector::value(dods_int32 *b) const { value_worker(b); }
2498void Vector::value(dods_uint32 *b) const { value_worker(b); }
2499void Vector::value(dods_int64 *b) const { value_worker(b); }
2500void Vector::value(dods_uint64 *b) const { value_worker(b); }
2501void Vector::value(dods_float32 *b) const { value_worker(b); }
2502void Vector::value(dods_float64 *b) const { value_worker(b); }
2503
2504#if 0
2505template void Vector::value(dods_byte *v) const;
2506template void Vector::value(dods_int8 *v) const;
2507template void Vector::value(dods_int16 *v) const;
2508template void Vector::value(dods_uint16 *v) const;
2509template void Vector::value(dods_int32 *v) const;
2510template void Vector::value(dods_uint32 *v) const;
2511template void Vector::value(dods_int64 *v) const;
2512template void Vector::value(dods_uint64 *v) const;
2513template void Vector::value(dods_float32 *v) const;
2514template void Vector::value(dods_float64 *v) const;
2515#endif
2516
2517
2519void Vector::value(vector<string> &b) const
2520{
2521 if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
2522 b = d_str;
2523}
2524
2528{
2529 void *buffer = new char[width_ll(true)];
2530
2531 memcpy(buffer, d_buf, width_ll(true));
2532
2533 return buffer;
2534}
2536
2553{
2554#if 1
2555 if (v)
2556 Vector::add_var_nocopy(v->ptr_duplicate());
2557 else {
2558 delete d_proto;
2559 d_proto = nullptr;
2560 }
2561#else
2562 // Delete the current template variable
2563 if (d_proto) {
2564 delete d_proto;
2565 d_proto = 0;
2566 }
2567
2568 // if 'v' is null, just set _var to null and exit.
2569 if (!v) {
2570 d_proto = 0;
2571 }
2572 else {
2573 // Jose Garcia
2574 // By getting a copy of this object to be assigned to _var
2575 // we let the owner of 'v' to deallocate it as necessary.
2576 d_proto = v->ptr_duplicate();
2577
2578 // If 'v' has a name, use it as the name of the array. If v doesn't have
2579 // a name, then make sure to copy the array's name to it
2580 // so that software which uses the template's name will still work.
2581 if (!v->name().empty())
2582 set_name(v->name());
2583 else
2584 d_proto->set_name(name());
2585
2586 d_proto->set_parent(this); // Vector --> child
2587
2588 DBG(cerr << "Vector::add_var: Added variable " << v << " ("
2589 << v->name() << " " << v->type_name() << ")" << endl);
2590 }
2591#endif
2592}
2593
2594void Vector::add_var_nocopy(BaseType * v, Part)
2595{
2596 // Delete the current template variable, if it exists
2597 delete d_proto;
2598 d_proto = nullptr;
2599
2600 // if 'v' is null, just set _var to null and exit.
2601 if (v) {
2602 d_proto = v;
2603
2604 // If 'v' has a name, use it as the name of the array. If it *is*
2605 // empty, then make sure to copy the array's name to the template
2606 // so that software which uses the template's name will still work.
2607 if (!v->name().empty())
2608 set_name(v->name());
2609 else
2610 d_proto->set_name(name());
2611
2612 d_proto->set_parent(this); // Vector is the parent; proto is the child
2613
2614 DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
2615 << v->name() << " " << v->type_name() << ")" << endl);
2616 }
2617}
2618
2619bool Vector::check_semantics(string & msg, bool)
2620{
2621 return BaseType::check_semantics(msg);
2622}
2623
2624
2631bool Vector::is_dap4_projected(std::vector<std::string> &inventory)
2632{
2633 bool has_projected_dap4 = false;
2634 if(send_p()) {
2635 if(d_proto->is_constructor_type()){
2636 has_projected_dap4 = d_proto->is_dap4_projected(inventory) || attributes()->has_dap4_types(FQN(),inventory);
2637 }
2638 else {
2639 has_projected_dap4 = prototype()->is_dap4();
2640 if(has_projected_dap4) {
2641 inventory.emplace_back(prototype()->type_name() + " " + FQN());
2642 }
2643 has_projected_dap4 |= attributes()->has_dap4_types(FQN(), inventory);
2644 }
2645 if(has_projected_dap4) {
2646 inventory.emplace_back(type_name() + " " + FQN());
2647 }
2648 }
2649 return has_projected_dap4;
2650}
2651
2652
2653
2654
2655
2656
2665void Vector::dump(ostream &strm) const
2666{
2667 strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
2668 DapIndent::Indent();
2669 BaseType::dump(strm);
2670 strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
2671 if (d_proto) {
2672 strm << DapIndent::LMarg << "base type:" << endl;
2673 DapIndent::Indent();
2674 d_proto->dump(strm);
2675 DapIndent::UnIndent();
2676 }
2677 else {
2678 strm << DapIndent::LMarg << "base type: not set" << endl;
2679 }
2680 strm << DapIndent::LMarg << "vector contents:" << endl;
2681 DapIndent::Indent();
2682 for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
2683 if (d_compound_buf[i])
2684 d_compound_buf[i]->dump(strm);
2685 else
2686 strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
2687 }
2688 DapIndent::UnIndent();
2689 strm << DapIndent::LMarg << "strings:" << endl;
2690 DapIndent::Indent();
2691 for (unsigned i = 0; i < d_str.size(); i++) {
2692 strm << DapIndent::LMarg << d_str[i] << endl;
2693 }
2694 DapIndent::UnIndent();
2695 if (d_buf) {
2696 switch (d_proto != 0 ? d_proto->type() : 0) {
2697 case dods_byte_c:
2698 case dods_char_c:
2699 strm << DapIndent::LMarg << "_buf: ";
2700 strm.write(d_buf, d_length);
2701 strm << endl;
2702 break;
2703
2704 case 0:
2705 default:
2706 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
2707 break;
2708 }
2709 }
2710 else {
2711 strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
2712 }
2713
2714 DapIndent::UnIndent();
2715}
2716
2717} // namespace libdap
2718
Definition: crc.h:79
void AddData(const uint8_t *pData, const uint32_t length)
Definition: crc.h:100
The basic data type for the DODS DAP types.
Definition: BaseType.h:120
virtual bool is_dap4_projected(std::vector< string > &projected_dap4_inventory)
Definition: BaseType.cc:1323
virtual string type_name() const
Returns the type of the class instance as a string.
Definition: BaseType.cc:376
virtual bool read()
Read data into a local buffer.
Definition: BaseType.cc:905
virtual string name() const
Returns the name of the class instance.
Definition: BaseType.cc:317
virtual bool read_p()
Has this variable been read?
Definition: BaseType.cc:477
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:1305
virtual void set_read_p(bool state)
Sets the value of the read_p property.
Definition: BaseType.cc:513
virtual string dataset() const
Returns the name of the dataset used to create this instance.
Definition: BaseType.cc:355
virtual void set_parent(BaseType *parent)
Definition: BaseType.cc:730
virtual int element_count(bool leaves=false)
Count the members of constructor types.
Definition: BaseType.cc:440
void dump(ostream &strm) const override
dumps information about this object
Definition: BaseType.cc:287
virtual void set_name(const string &n)
Sets the name of the class instance.
Definition: BaseType.cc:341
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:409
virtual D4Attributes * attributes()
Definition: BaseType.cc:596
virtual std::string FQN() const
Definition: BaseType.cc:329
virtual bool send_p()
Should this variable be sent?
Definition: BaseType.cc:551
virtual void set_send_p(bool state)
Definition: BaseType.cc:565
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 bool check_semantics(string &msg, bool all=false)
Compare an object's current state with the semantics of its type.
Definition: BaseType.cc:1215
virtual BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr)
Returns a pointer to a member of a constructor class.
Definition: BaseType.cc:764
virtual Type type() const
Returns the type of the class instance.
Definition: BaseType.cc:362
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 ...
bool has_dap4_types(const std::string &path, std::vector< std::string > &inventory) const
Marshaller that knows how to marshal/serialize dap data objects to a C++ iostream using DAP4's receiv...
virtual void put_vector_float32(char *val, int64_t num_elem)
Write a fixed size vector.
virtual void put_vector(char *val, int64_t num_bytes)
Write a fixed size vector.
virtual void put_vector_float64(char *val, int64_t num_elem)
Write a fixed size vector of float64s.
Read data from the stream made by D4StreamMarshaller.
A class for error processing.
Definition: Error.h:94
A class for software fault reporting.
Definition: InternalErr.h:65
abstract base class used to marshal/serialize dap data objects
Definition: Marshaller.h:50
abstract base class used to unmarshall/deserialize dap data objects
Definition: UnMarshaller.h:55
Holds a one-dimensional collection of DAP2 data types.
Definition: Vector.h:83
virtual void reserve_value_capacity_ll_byte(uint64_t numBytes)
Definition: Vector.cc:1867
bool deserialize(UnMarshaller &um, DDS *dds, bool reuse=false) override
Receive data from the net.
Definition: Vector.cc:855
void set_send_p(bool state) override
Indicates that the data is ready to send.
Definition: Vector.cc:363
int64_t width_ll(bool constrained=false) const override
Return the number of bytes needed to hold the array data.
Definition: Vector.h:208
void dump(ostream &strm) const override
dumps information about this object
Definition: Vector.cc:2665
void compute_checksum(Crc32 &checksum) override
include the data for this variable in the checksum DAP4 includes a checksum with every data response....
Definition: Vector.cc:959
virtual unsigned int get_value_capacity() const
Definition: Vector.cc:1700
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:1606
void add_var(BaseType *v, Part p=nil) override
Add the BaseType pointer to this constructor type instance.
Definition: Vector.cc:2552
int length() const override
Returns the number of elements in the vector. Note that some child classes of Vector use the length o...
Definition: Vector.h:218
int64_t length_ll() const override
Get the number of elements in this Vector/Array This version of the function deprecates length() whic...
Definition: Vector.h:226
void set_read_p(bool state) override
Indicates that the data is ready to send.
Definition: Vector.cc:400
int element_count(bool leaves) override
Count the members of constructor types.
Definition: Vector.cc:342
void set_length_ll(int64_t l) override
Set the number of elements in this Vector/Array This version of the function deprecates set_length() ...
Definition: Vector.cc:446
void set_vec(unsigned int i, BaseType *val)
Sets element i to value val.
Definition: Vector.cc:1585
bool is_dap4_projected(std::vector< std::string > &projected_dap4_inventory) override
Definition: Vector.cc:2631
void set_name(const std::string &name) override
Sets the name of the class instance.
Definition: Vector.cc:332
bool check_semantics(string &msg, bool all=false) override
Compare an object's current state with the semantics of its type.
Definition: Vector.cc:2619
void intern_data() override
Read data into this variable.
Definition: Vector.cc:1001
virtual void reserve_value_capacity_ll()
Definition: Vector.cc:1856
unsigned int val2buf(void *val, bool reuse=false) override
Reads data into the Vector buffer.
Definition: Vector.cc:1329
BaseType * var(const string &name="", bool exact_match=true, btp_stack *s=nullptr) override
Definition: Vector.cc:486
virtual uint64_t set_value_slice_from_row_major_vector(const Vector &rowMajorData, uint64_t startElement)
Definition: Vector.cc:1901
virtual void * value()
Definition: Vector.cc:2527
bool serialize(ConstraintEvaluator &eval, DDS &dds, Marshaller &m, bool ce_eval=true) override
Serialize a Vector.
Definition: Vector.cc:752
void vec_resize(int l)
Definition: Vector.cc:637
virtual void reserve_value_capacity()
Definition: Vector.cc:1780
unsigned int buf2val(void **val) override
Copies data from the Vector buffer.
Definition: Vector.cc:1452
void clear_local_data() override
Definition: Vector.cc:1672
Vector(const string &n, BaseType *v, const Type &t, bool is_dap4=false)
The Vector constructor.
Definition: Vector.cc:259
void set_length(int64_t l) override
Sets the length of the vector. This function does not allocate any new space.
Definition: Vector.cc:434
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