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