libdap  Updated for version 3.17.0
Vector.cc
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 
00025 // (c) COPYRIGHT URI/MIT 1995-1999
00026 // Please read the full copyright statement in the file COPYRIGHT_URI.
00027 //
00028 // Authors:
00029 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00030 
00031 // Implementation for class Vector. This class is the basis for all the
00032 // vector-type classes in libdap's <Array, List>.
00033 //
00034 // 11/21/95 jhrg
00035 
00036 #include "config.h"
00037 
00038 #include <cstring>
00039 #include <cassert>
00040 
00041 //#define DODS_DEBUG 1
00042 
00043 #include <sstream>
00044 #include <vector>
00045 #include <algorithm>
00046 #include <typeinfo>
00047 
00048 #include <stdint.h>
00049 
00050 #include "crc.h"
00051 
00052 #include "Vector.h"
00053 #include "Marshaller.h"
00054 #include "UnMarshaller.h"
00055 
00056 #include "D4StreamMarshaller.h"
00057 #include "D4StreamUnMarshaller.h"
00058 
00059 #include "D4Enum.h"
00060 
00061 #include "Type.h"
00062 #include "dods-datatypes.h"
00063 #include "escaping.h"
00064 #include "util.h"
00065 #include "debug.h"
00066 #include "InternalErr.h"
00067 
00068 #undef CLEAR_LOCAL_DATA
00069 
00070 using std::cerr;
00071 using std::endl;
00072 
00073 namespace libdap {
00074 
00075 void Vector::m_duplicate(const Vector & v)
00076 {
00077     d_length = v.d_length;
00078 
00079     // _var holds the type of the elements. That is, it holds a BaseType
00080     // which acts as a template for the type of each element.
00081     if (v.d_proto) {
00082         d_proto = v.d_proto->ptr_duplicate(); // use ptr_duplicate()
00083         d_proto->set_parent(this); // ptr_duplicate does not set d_parent.
00084     }
00085     else {
00086         d_proto = 0;
00087     }
00088 
00089     // d_compound_buf and d_buf (further down) hold the values of the Vector. The field
00090     // d_compound_buf is used when the Vector holds non-numeric data (including strings
00091     // although it used to be that was not the case jhrg 2/10/05) while d_buf
00092     // holds numeric values.
00093     if (v.d_compound_buf.empty()) {
00094         d_compound_buf = v.d_compound_buf;
00095     }
00096     else {
00097         // Failure to set the size will make the [] operator barf on the LHS
00098         // of the assignment inside the loop.
00099         d_compound_buf.resize(d_length);
00100         for (int i = 0; i < d_length; ++i) {
00101             // There's no need to call set_parent() for each element; we
00102             // maintain the back pointer using the d_proto member. These
00103             // instances are used to hold _values_ only while the d_proto
00104             // field holds the type information for the elements.
00105             d_compound_buf[i] = v.d_compound_buf[i]->ptr_duplicate();
00106         }
00107     }
00108 
00109     // copy the strings. This copies the values.
00110     d_str = v.d_str;
00111 
00112     // copy numeric values if there are any.
00113     d_buf = 0; // init to null
00114     if (v.d_buf) // only copy if data present
00115         val2buf(v.d_buf); // store v's value in this's _BUF.
00116 
00117     d_capacity = v.d_capacity;
00118 }
00119 
00124 bool Vector::m_is_cardinal_type() const
00125 {
00126     // Not cardinal if no d_proto at all!
00127     if (!d_proto) {
00128         return false;
00129     }
00130 
00131     switch (d_proto->type()) {
00132         case dods_byte_c:
00133         case dods_char_c:
00134         case dods_int16_c:
00135         case dods_uint16_c:
00136         case dods_int32_c:
00137         case dods_uint32_c:
00138         case dods_float32_c:
00139         case dods_float64_c:
00140                 // New cardinal types for DAP4
00141         case dods_int8_c:
00142         case dods_uint8_c:
00143         case dods_int64_c:
00144         case dods_uint64_c:
00145 
00146         case dods_enum_c:
00147             return true;
00148             break;
00149 
00150             // These must be handled differently.
00151         case dods_str_c:
00152         case dods_url_c:
00153         case dods_opaque_c:
00154 
00155         case dods_array_c:
00156 
00157         case dods_structure_c:
00158         case dods_sequence_c:
00159         case dods_grid_c:
00160             return false;
00161             break;
00162 
00163         default:
00164             assert("Vector::var: Unrecognized type");
00165             return false;
00166     }
00167 }
00168 
00181 unsigned int Vector::m_create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
00182 {
00183     // Make sure we HAVE a _var, or we cannot continue.
00184     if (!d_proto) {
00185         throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
00186     }
00187 
00188     // Make sure we only do this for the correct data types.
00189     if (!m_is_cardinal_type()) {
00190         throw InternalErr(__FILE__, __LINE__, "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
00191     }
00192 
00193     m_delete_cardinal_data_buffer();
00194 
00195     // Handle this special case where this is an array that holds no values
00196     if (numEltsOfType == 0)
00197         return 0;
00198 
00199     // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
00200     unsigned int bytesPerElt = d_proto->width();
00201     unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
00202     d_buf = new char[bytesNeeded];
00203 
00204     d_capacity = numEltsOfType;
00205     return bytesNeeded;
00206 }
00207 
00209 void Vector::m_delete_cardinal_data_buffer()
00210 {
00211         delete[] d_buf;
00212         d_buf = 0;
00213         d_capacity = 0;
00214 }
00215 
00219 template<class CardType>
00220 void Vector::m_set_cardinal_values_internal(const CardType* fromArray, int numElts)
00221 {
00222     if (numElts < 0) {
00223         throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
00224     }
00225     if (!fromArray) {
00226         throw InternalErr(__FILE__, __LINE__, "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
00227     }
00228     set_length(numElts);
00229     m_create_cardinal_data_buffer_for_type(numElts);
00230     memcpy(d_buf, fromArray, numElts * sizeof(CardType));
00231     set_read_p(true);
00232 }
00233 
00249 Vector::Vector(const string & n, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
00250     BaseType(n, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
00251 {
00252     if (v)
00253         add_var(v);
00254 
00255     DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
00256     if (d_proto)
00257         d_proto->set_parent(this);
00258 }
00259 
00278 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t, bool is_dap4 /* default:false */) :
00279     BaseType(n, d, t, is_dap4), d_length(-1), d_proto(0), d_buf(0), d_compound_buf(0), d_capacity(0)
00280 {
00281     if (v)
00282         add_var(v);
00283 
00284     DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
00285     if (d_proto)
00286         d_proto->set_parent(this);
00287 }
00288 
00290 Vector::Vector(const Vector & rhs) :
00291     BaseType(rhs)
00292 {
00293     DBG2(cerr << "Entering Vector const ctor for object: " << this <<
00294             endl); DBG2(cerr << "RHS: " << &rhs << endl);
00295 
00296     m_duplicate(rhs);
00297 }
00298 
00299 Vector::~Vector()
00300 {
00301     DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
00302 
00303     delete d_proto;
00304     d_proto = 0;
00305 
00306     // Clears all buffers
00307     clear_local_data();
00308 
00309     DBG2(cerr << "Exiting ~Vector" << endl);
00310 }
00311 
00312 Vector & Vector::operator=(const Vector & rhs)
00313 {
00314     if (this == &rhs)
00315         return *this;
00316 
00317     dynamic_cast<BaseType &> (*this) = rhs;
00318 
00319     m_duplicate(rhs);
00320 
00321     return *this;
00322 }
00323 
00324 void Vector::set_name(const std::string& name)
00325 {
00326     BaseType::set_name(name);
00327     // We need to set the prototype name as well since
00328     // this is what gets output in the dds!  Otherwise, there's a mismatch.
00329     if (d_proto) {
00330         d_proto->set_name(name);
00331     }
00332 }
00333 
00334 int Vector::element_count(bool leaves)
00335 {
00336     if (!leaves)
00337         return 1;
00338     else
00339         return d_proto->element_count(leaves);
00340         // var() only works for simple types!
00341         // jhrg 8/19/13 return var(0)->element_count(leaves);
00342 }
00343 
00344 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
00345 // from BaseType's version in that they set both the Vector object's copy of
00346 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
00347 // is a scalar, but does matter when it is an aggregate.
00348 
00355 void Vector::set_send_p(bool state)
00356 {
00357     d_proto->set_send_p(state);
00358     BaseType::set_send_p(state);
00359 }
00360 
00367 void Vector::set_read_p(bool state)
00368 {
00369     if (d_proto) {
00370         d_proto->set_read_p(state);
00371     }
00372     BaseType::set_read_p(state);
00373 }
00374 
00392 BaseType *Vector::var(const string &n, bool exact, btp_stack *s)
00393 {
00394     string name = www2id(n);
00395     DBG2(cerr << "Vector::var: Looking for " << name << endl);
00396 
00397     // If this is a Vector of constructor types, look for 'name' recursively.
00398     // Make sure to check for the case where name is the default (the empty
00399     // string). 9/1/98 jhrg
00400     if (d_proto->is_constructor_type()) {
00401         if (name == "" || d_proto->name() == name) {
00402             if (s)
00403                 s->push(this);
00404             return d_proto;
00405         }
00406         else {
00407             BaseType * result = d_proto->var(name, exact, s);
00408             if (result && s)
00409                 s->push(this);
00410             return result;
00411         }
00412     }
00413     else {
00414         return d_proto;
00415     }
00416 }
00417 
00428 BaseType *Vector::var(const string & n, btp_stack & s)
00429 {
00430     string name = www2id(n);
00431 
00432     if (d_proto->is_constructor_type())
00433         return d_proto->var(name, s);
00434     else {
00435         s.push((BaseType *) this);
00436         return d_proto;
00437     }
00438 }
00439 
00451 BaseType *Vector::var(unsigned int i)
00452 {
00453 
00454     switch (d_proto->type()) {
00455         case dods_byte_c:
00456         case dods_char_c:
00457         case dods_int8_c:
00458         case dods_uint8_c:
00459         case dods_int16_c:
00460         case dods_uint16_c:
00461         case dods_int32_c:
00462         case dods_uint32_c:
00463         case dods_int64_c:
00464         case dods_uint64_c:
00465 
00466         case dods_enum_c:
00467 
00468         case dods_float32_c:
00469         case dods_float64_c:
00470             // Transfer the ith value to the BaseType *d_proto
00471             d_proto->val2buf(d_buf + (i * d_proto->width()));
00472             return d_proto;
00473             break;
00474 
00475         case dods_str_c:
00476         case dods_url_c:
00477             d_proto->val2buf(&d_str[i]);
00478             return d_proto;
00479             break;
00480 
00481         case dods_opaque_c:
00482         case dods_array_c:
00483         case dods_structure_c:
00484         case dods_sequence_c:
00485         case dods_grid_c:
00486             return d_compound_buf[i];
00487             break;
00488 
00489         default:
00490             throw Error ("Vector::var: Unrecognized type");
00491             break;
00492     }
00493 
00494     return 0;
00495 }
00496 
00503 unsigned int Vector::width(bool constrained) const
00504 {
00505     // Jose Garcia
00506         assert(d_proto);
00507 
00508     return length() * d_proto->width(constrained);
00509 }
00510 
00515 int Vector::length() const
00516 {
00517     return d_length;
00518 }
00519 
00522 void Vector::set_length(int l)
00523 {
00524     d_length = l;
00525 }
00526 
00535 void Vector::vec_resize(int l)
00536 {
00537     // I added this check, which alters the behavior of the method. jhrg 8/14/13
00538     if (m_is_cardinal_type())
00539         throw InternalErr(__FILE__, __LINE__, "Vector::vec_resize() is applicable to compound types only");
00540 
00541     d_compound_buf.resize((l > 0) ? l : 0, 0); // Fill with NULLs
00542     d_capacity = l; // capacity in terms of number of elements.
00543 }
00544 
00561 void Vector::intern_data(ConstraintEvaluator &eval, DDS &dds)
00562 {
00563     DBG(cerr << "Vector::intern_data: " << name() << endl);
00564     if (!read_p())
00565         read(); // read() throws Error and InternalErr
00566 
00567     // length() is not capacity; it must be set explicitly in read().
00568     int num = length();
00569 
00570     switch (d_proto->type()) {
00571         case dods_byte_c:
00572         case dods_int16_c:
00573         case dods_uint16_c:
00574         case dods_int32_c:
00575         case dods_uint32_c:
00576         case dods_float32_c:
00577         case dods_float64_c:
00578             // For these cases, read() puts the data into d_buf,
00579                 // which is what we need.
00580             break;
00581 
00582         case dods_str_c:
00583         case dods_url_c:
00584             // For these cases, read() will put the data into d_str[],
00585                 // which is also what we need.
00586             break;
00587 
00588         case dods_array_c:
00589             // This is an error since there can never be an Array of Array.
00590             throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
00591             break;
00592 
00593         case dods_structure_c:
00594         case dods_sequence_c:
00595         case dods_grid_c:
00596             DBG(cerr << "Vector::intern_data: found ctor" << endl);
00597             // For these cases, we need to call read() for each of the 'num'
00598             // elements in the 'd_compound_buf[]' array of BaseType object pointers.
00599             //
00600             // I changed the test here from '... = 0' to '... < num' to accommodate
00601             // the case where the array is zero-length.
00602             if (d_compound_buf.capacity() < (unsigned)num)
00603                 throw InternalErr(__FILE__, __LINE__, "The capacity of this Vector is less than the number of elements.");
00604 
00605             for (int i = 0; i < num; ++i)
00606                 d_compound_buf[i]->intern_data(eval, dds);
00607 
00608             break;
00609 
00610         default:
00611             throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
00612             break;
00613     }
00614 }
00615 
00627 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds, Marshaller &m, bool ce_eval)
00628 {
00629 #if 0
00630     dds.timeout_on();
00631 #endif
00632     if (!read_p())
00633         read(); // read() throws Error and InternalErr
00634 
00635     if (ce_eval && !eval.eval_selection(dds, dataset()))
00636         return true;
00637 #if 0
00638     dds.timeout_off();
00639 #endif
00640     // length() is not capacity; it must be set explicitly in read().
00641     int num = length();
00642 
00643     bool status = false;
00644 
00645     switch (d_proto->type()) {
00646         case dods_byte_c:
00647             m.put_vector(d_buf, num, *this);
00648             status = true;
00649             break;
00650 
00651         case dods_int16_c:
00652         case dods_uint16_c:
00653         case dods_int32_c:
00654         case dods_uint32_c:
00655         case dods_float32_c:
00656         case dods_float64_c:
00657             m.put_vector(d_buf, num, d_proto->width(), *this);
00658             status = true;
00659 
00660             break;
00661 
00662         case dods_str_c:
00663         case dods_url_c:
00664             if (d_str.capacity() == 0)
00665                 throw InternalErr(__FILE__, __LINE__, "The capacity of the string vector is 0");
00666 
00667             m.put_int(num);
00668 
00669             for (int i = 0; i < num; ++i)
00670                 m.put_str(d_str[i]);
00671 
00672             status = true;
00673             break;
00674 
00675         case dods_array_c:
00676         case dods_structure_c:
00677         case dods_sequence_c:
00678         case dods_grid_c:
00679             //Jose Garcia
00680             // Not setting the capacity of d_compound_buf is an internal error.
00681             if (d_compound_buf.capacity() == 0)
00682                 throw InternalErr(__FILE__, __LINE__, "The capacity of *this* vector is 0.");
00683 
00684             m.put_int(num);
00685             status = true;
00686             for (int i = 0; i < num && status; ++i)
00687                 status = status && d_compound_buf[i]->serialize(eval, dds, m, false);
00688 
00689             break;
00690 
00691         default:
00692             throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
00693             break;
00694     }
00695 
00696 #ifdef CLEAR_LOCAL_DATA
00697     clear_local_data();
00698 #endif
00699 
00700     return status;
00701 }
00702 
00703 // Read an object from the network and internalize it. For a Vector this is
00704 // handled differently for a `cardinal' type. Vectors of Cardinals are
00705 // stored using the `C' representations because these objects often are used
00706 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
00707 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
00708 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
00709 // Grid are vectors of the libdap Structure, ... classes).
00710 //
00711 // The boolean parameter REUSE determines whether internal storage is reused
00712 // or not. If true, the _buf member is assumed to be large enough to hold the
00713 // incoming cardinal data and is *not* reallocated. If false, new storage is
00714 // allocated. If the internal buffer has not yet been allocated, then this
00715 // parameter has no effect (i.e., storage is allocated). This parameter
00716 // effects storage for cardinal data only.
00717 //
00718 // Returns: True is successful, false otherwise.
00719 
00720 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
00721 {
00722     unsigned int num;
00723     unsigned i = 0;
00724 
00725     switch (d_proto->type()) {
00726         case dods_byte_c:
00727         case dods_int16_c:
00728         case dods_uint16_c:
00729         case dods_int32_c:
00730         case dods_uint32_c:
00731         case dods_float32_c:
00732         case dods_float64_c:
00733             um.get_int((int &) num);
00734 
00735             DBG(cerr << "Vector::deserialize: num = " << num << endl);
00736             DBG(cerr << "Vector::deserialize: length = " << length() << endl);
00737 
00738             if (length() == -1)
00739                 set_length(num);
00740 
00741             if (num != (unsigned int) length())
00742                 throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes for the variable '" + name() + "'.");
00743 
00744             if (!d_buf || !reuse) {
00745                 // Make d_buf be large enough for length() elements of _var->type()
00746                 // m_create...() deletes the old buffer.
00747                 m_create_cardinal_data_buffer_for_type(length());
00748                 DBG(cerr << "Vector::deserialize: allocating "
00749                         << width() << " bytes for an array of "
00750                         << length() << " " << d_proto->type_name() << endl);
00751             }
00752 
00753             // Added to accommodate zero-length arrays.
00754             // Note that the rest of the cases will just send the size without data
00755             // but that these calls trigger error testing in the UnMarshaller code.
00756             // jhrg 1/28/16
00757             if (num == 0)
00758                 return true;
00759 
00760             if (d_proto->type() == dods_byte_c)
00761                 um.get_vector((char **) &d_buf, num, *this);
00762             else
00763                 um.get_vector((char **) &d_buf, num, d_proto->width(), *this);
00764 
00765             DBG(cerr << "Vector::deserialize: read " << num << " elements\n");
00766 
00767             break;
00768 
00769         case dods_str_c:
00770         case dods_url_c:
00771             um.get_int((int &) num);
00772 
00773             if (length() == -1)
00774                 set_length(num);
00775 
00776             if (num != (unsigned int) length())
00777                 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
00778 
00779             d_str.resize((num > 0) ? num : 0); // Fill with NULLs
00780             d_capacity = num; // capacity is number of strings we can fit.
00781 
00782             for (i = 0; i < num; ++i) {
00783                 string str;
00784                 um.get_str(str);
00785                 d_str[i] = str;
00786 
00787             }
00788 
00789             break;
00790 
00791         case dods_array_c:
00792             // TODO
00793         case dods_structure_c:
00794         case dods_sequence_c:
00795         case dods_grid_c:
00796             um.get_int((int &) num);
00797 
00798             if (length() == -1)
00799                 set_length(num);
00800 
00801             if (num != (unsigned int) length())
00802                 throw InternalErr(__FILE__, __LINE__, "The client sent declarations and data with mismatched sizes.");
00803 
00804             vec_resize(num);
00805 
00806             for (i = 0; i < num; ++i) {
00807                 d_compound_buf[i] = d_proto->ptr_duplicate();
00808                 d_compound_buf[i]->deserialize(um, dds);
00809             }
00810 
00811             break;
00812 
00813         default:
00814             throw InternalErr(__FILE__, __LINE__, "Unknown type!");
00815             break;
00816     }
00817 
00818     return false;
00819 }
00820 
00821 void Vector::compute_checksum(Crc32 &checksum)
00822 {
00823     switch (d_proto->type()) {
00824         case dods_byte_c:
00825         case dods_char_c:
00826         case dods_int8_c:
00827         case dods_uint8_c:
00828 
00829         case dods_int16_c:
00830         case dods_uint16_c:
00831 
00832         case dods_int32_c:
00833         case dods_uint32_c:
00834         case dods_float32_c:
00835 
00836         case dods_int64_c:
00837         case dods_uint64_c:
00838         case dods_float64_c:
00839 
00840         case dods_enum_c:
00841                 checksum.AddData(reinterpret_cast<uint8_t*>(d_buf), length() * d_proto->width());
00842                 break;
00843 
00844         case dods_str_c:
00845         case dods_url_c:
00846                 for (int64_t i = 0, e = length(); i < e; ++i)
00847                         checksum.AddData(reinterpret_cast<const uint8_t*>(d_str[i].data()), d_str[i].length());
00848             break;
00849 
00850         case dods_opaque_c:
00851         case dods_structure_c:
00852         case dods_sequence_c:
00853                 d_proto->compute_checksum(checksum);
00854                 break;
00855 
00856         case dods_array_c:      // No array of array
00857         case dods_grid_c:       // No grids in DAP4
00858         default:
00859             throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
00860             break;
00861     }
00862 }
00863 
00864 void Vector::intern_data(/*Crc32 &checksum, DMR &dmr, ConstraintEvaluator &eval*/)
00865 {
00866     if (!read_p())
00867         read(); // read() throws Error and InternalErr
00868 
00869     switch (d_proto->type()) {
00870         case dods_byte_c:
00871         case dods_char_c:
00872         case dods_int8_c:
00873         case dods_uint8_c:
00874         case dods_int16_c:
00875         case dods_uint16_c:
00876         case dods_int32_c:
00877         case dods_uint32_c:
00878         case dods_int64_c:
00879         case dods_uint64_c:
00880 
00881         case dods_enum_c:
00882 
00883         case dods_float32_c:
00884         case dods_float64_c:
00885 
00886         case dods_str_c:
00887         case dods_url_c:
00888 #if 0
00889                 compute_checksum(checksum);
00890 #endif
00891             break;
00892 
00893         case dods_opaque_c:
00894         case dods_structure_c:
00895         case dods_sequence_c:
00896             // Modified the assert here from '... != 0' to '... >= length())
00897             // to accommodate the case of a zero-length array. jhrg 1/28/16
00898             assert(d_compound_buf.capacity() >= (unsigned)length());
00899 
00900             for (int i = 0, e = length(); i < e; ++i)
00901                 d_compound_buf[i]->intern_data(/*checksum, dmr, eval*/);
00902             break;
00903 
00904         case dods_array_c:      // No Array of Array in DAP4 either...
00905         case dods_grid_c:
00906         default:
00907                 throw InternalErr(__FILE__, __LINE__, "Unknown or unsupported datatype (" + d_proto->type_name() + ").");
00908             break;
00909     }
00910 }
00911 
00912 void
00913 Vector::serialize(D4StreamMarshaller &m, DMR &dmr, /*ConstraintEvaluator &eval,*/ bool filter /*= false*/)
00914 {
00915     if (!read_p())
00916         read(); // read() throws Error and InternalErr
00917 #if 0
00918     if (filter && !eval.eval_selection(dmr, dataset()))
00919         return true;
00920 #endif
00921     int64_t num = length();     // The constrained length in elements
00922 
00923     DBG(cerr << __PRETTY_FUNCTION__ << ", num: " << num << endl);
00924 
00925     // Added in case we're trying to serialize a zero-length array. jhrg 1/27/16
00926     if (num == 0)
00927         return;
00928 
00929     switch (d_proto->type()) {
00930         case dods_byte_c:
00931         case dods_char_c:
00932         case dods_int8_c:
00933         case dods_uint8_c:
00934             m.put_vector(d_buf, num);
00935             break;
00936 
00937         case dods_int16_c:
00938         case dods_uint16_c:
00939         case dods_int32_c:
00940         case dods_uint32_c:
00941         case dods_int64_c:
00942         case dods_uint64_c:
00943                 m.put_vector(d_buf, num, d_proto->width());
00944                 break;
00945 
00946         case dods_enum_c:
00947                 if (d_proto->width() == 1)
00948                         m.put_vector(d_buf, num);
00949                 else
00950                         m.put_vector(d_buf, num, d_proto->width());
00951                 break;
00952 
00953         case dods_float32_c:
00954             m.put_vector_float32(d_buf, num);
00955             break;
00956 
00957         case dods_float64_c:
00958             m.put_vector_float64(d_buf, num);
00959             break;
00960 
00961         case dods_str_c:
00962         case dods_url_c:
00963             assert((int64_t)d_str.capacity() >= num);
00964 
00965             for (int64_t i = 0; i < num; ++i)
00966                 m.put_str(d_str[i]);
00967 
00968             break;
00969 
00970         case dods_array_c:
00971                 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
00972 
00973         case dods_opaque_c:
00974         case dods_structure_c:
00975         case dods_sequence_c:
00976             assert(d_compound_buf.capacity() >= 0);
00977 
00978             for (int64_t i = 0; i < num; ++i)
00979                 d_compound_buf[i]->serialize(m, dmr, /*eval,*/ filter);
00980 
00981             break;
00982 
00983         case dods_grid_c:
00984                 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
00985 
00986         default:
00987             throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
00988             break;
00989     }
00990 
00991 #ifdef CLEAR_LOCAL_DATA
00992     clear_local_data();
00993 #endif
00994 }
00995 
00996 void
00997 Vector::deserialize(D4StreamUnMarshaller &um, DMR &dmr)
00998 {
00999     if (m_is_cardinal_type()) {
01000         if (d_buf)
01001             m_delete_cardinal_data_buffer();
01002         if (!d_buf)
01003             m_create_cardinal_data_buffer_for_type(length());
01004     }
01005 
01006     DBG(cerr << __FUNCTION__ << name() << ", length(): " << length() << endl);
01007 
01008     // Added in case we're trying to deserialize a zero-length array. jhrg 1/27/16
01009     if (length() == 0)
01010         return;
01011 
01012     switch (d_proto->type()) {
01013         case dods_byte_c:
01014         case dods_char_c:
01015         case dods_int8_c:
01016         case dods_uint8_c:
01017                 um.get_vector((char *)d_buf, length());
01018                 break;
01019 
01020         case dods_int16_c:
01021         case dods_uint16_c:
01022         case dods_int32_c:
01023         case dods_uint32_c:
01024         case dods_int64_c:
01025         case dods_uint64_c:
01026                 um.get_vector((char *)d_buf, length(), d_proto->width());
01027                 break;
01028 
01029         case dods_enum_c:
01030                 if (d_proto->width() == 1)
01031                         um.get_vector((char *)d_buf, length());
01032                 else
01033                         um.get_vector((char *)d_buf, length(), d_proto->width());
01034                 break;
01035 
01036         case dods_float32_c:
01037             um.get_vector_float32((char *)d_buf, length());
01038             break;
01039 
01040         case dods_float64_c:
01041                 um.get_vector_float64((char *)d_buf, length());
01042             break;
01043 
01044         case dods_str_c:
01045         case dods_url_c: {
01046                 int64_t len = length();
01047             d_str.resize((len > 0) ? len : 0); // Fill with NULLs
01048             d_capacity = len; // capacity is number of strings we can fit.
01049 
01050             for (int64_t i = 0; i < len; ++i) {
01051                 um.get_str(d_str[i]);
01052             }
01053 
01054             break;
01055         }
01056 
01057         case dods_array_c:
01058                 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
01059 
01060         case dods_opaque_c:
01061         case dods_structure_c:
01062         case dods_sequence_c: {
01063             vec_resize(length());
01064 
01065             for (int64_t i = 0, end = length(); i < end; ++i) {
01066                 d_compound_buf[i] = d_proto->ptr_duplicate();
01067                 d_compound_buf[i]->deserialize(um, dmr);
01068             }
01069 
01070             break;
01071         }
01072 
01073         case dods_grid_c:
01074                 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
01075 
01076         default:
01077             throw InternalErr(__FILE__, __LINE__, "Unknown type.");
01078             break;
01079     }
01080 }
01081 
01109 unsigned int Vector::val2buf(void *val, bool reuse)
01110 {
01111     // Jose Garcia
01112 
01113     // Added for zero-length arrays - support in the handlers. jhrg 1/29/16
01114     if (!val && length() == 0)
01115         return 0;
01116 
01117     // I *think* this method has been mainly designed to be use by read which
01118     // is implemented in the surrogate library. Passing NULL as a pointer to
01119     // this method will be an error of the creator of the surrogate library.
01120     // Even though I recognize the fact that some methods inside libdap++ can
01121     // call val2buf, I think by now no coding bugs such as misusing val2buf
01122     // will be in libdap++, so it will be an internal error from the
01123     // surrogate library.
01124     if (!val)
01125         throw InternalErr(__FILE__, __LINE__, "The incoming pointer does not contain any data.");
01126 
01127     switch (d_proto->type()) {
01128         case dods_byte_c:
01129         case dods_char_c:
01130         case dods_int8_c:
01131         case dods_uint8_c:
01132         case dods_int16_c:
01133         case dods_uint16_c:
01134         case dods_int32_c:
01135         case dods_uint32_c:
01136         case dods_int64_c:
01137         case dods_uint64_c:
01138 
01139         case dods_enum_c:
01140 
01141         case dods_float32_c:
01142         case dods_float64_c:
01143 #if 0
01144                 if (d_buf && !reuse)
01145                 m_delete_cardinal_data_buffer();
01146 #endif
01147             // First time or no reuse (free'd above)
01148             if (!d_buf || !reuse)
01149                 m_create_cardinal_data_buffer_for_type(length());
01150 
01151             // width(true) returns the size in bytes given the constraint
01152             memcpy(d_buf, val, width(true));
01153             break;
01154 
01155         case dods_str_c:
01156         case dods_url_c:
01157             // Assume val points to an array of C++ string objects. Copy
01158             // them into the vector<string> field of this object.
01159             // Note: d_length is the number of elements in the Vector
01160             d_str.resize(d_length);
01161             d_capacity = d_length;
01162             for (int i = 0; i < d_length; ++i)
01163                 d_str[i] = *(static_cast<string *> (val) + i);
01164 
01165             break;
01166 
01167         default:
01168             throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
01169 
01170     }
01171 
01172     return width(true);
01173 }
01174 
01205 unsigned int Vector::buf2val(void **val)
01206 {
01207     // Jose Garcia
01208     // The same comment in Vector::val2buf applies here!
01209     if (!val)
01210         throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
01211 
01212     unsigned int wid = static_cast<unsigned int> (width(true /* constrained */));
01213 
01214     // This is the width computed using length(). The
01215     // length() property is changed when a projection
01216     // constraint is applied. Thus this is the number of
01217     // bytes in the buffer given the current constraint.
01218 
01219     switch (d_proto->type()) {
01220         case dods_byte_c:
01221         case dods_char_c:
01222         case dods_int8_c:
01223         case dods_uint8_c:
01224         case dods_int16_c:
01225         case dods_uint16_c:
01226         case dods_int32_c:
01227         case dods_uint32_c:
01228         case dods_int64_c:
01229         case dods_uint64_c:
01230 
01231         case dods_enum_c:
01232 
01233         case dods_float32_c:
01234         case dods_float64_c:
01235             if (!d_buf)
01236                 throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when cardinal type data buffer was empty!");
01237             if (!*val)
01238                 *val = new char[wid];
01239 
01240             memcpy(*val, d_buf, wid);
01241             return wid;
01242             break;
01243 
01244         case dods_str_c:
01245         case dods_url_c: {
01246                 if (d_str.empty())
01247                         throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when string data buffer was empty!");
01248             if (!*val)
01249                 *val = new string[d_length];
01250 
01251             for (int i = 0; i < d_length; ++i)
01252                 *(static_cast<string *> (*val) + i) = d_str[i];
01253 
01254             return width();
01255             break;
01256         }
01257 
01258         default:
01259             throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
01260     }
01261 
01262     //return wid;
01263 }
01264 
01285 void Vector::set_vec(unsigned int i, BaseType * val)
01286 {
01287         Vector::set_vec_nocopy(i, val->ptr_duplicate());
01288 }
01289 
01296 void Vector::set_vec_nocopy(unsigned int i, BaseType * val)
01297 {
01298     // Jose Garcia
01299     // This is a public method which allows users to set the elements
01300     // of *this* vector. Passing an invalid index, a NULL pointer or
01301     // mismatching the vector type are internal errors.
01302     if (i >= static_cast<unsigned int> (d_length))
01303         throw InternalErr(__FILE__, __LINE__, "Invalid data: index too large.");
01304     if (!val)
01305         throw InternalErr(__FILE__, __LINE__, "Invalid data: null pointer to BaseType object.");
01306     if (val->type() != d_proto->type())
01307         throw InternalErr(__FILE__, __LINE__, "invalid data: type of incoming object does not match *this* vector type.");
01308 
01309     if (i >= d_compound_buf.capacity())
01310         vec_resize(i + 10);
01311 
01312     d_compound_buf[i] = val;
01313 }
01314 
01324 void Vector::clear_local_data()
01325 {
01326     if (d_buf) {
01327         delete[] d_buf;
01328         d_buf = 0;
01329     }
01330 
01331     for (unsigned int i = 0; i < d_compound_buf.size(); ++i) {
01332         delete d_compound_buf[i];
01333         d_compound_buf[i] = 0;
01334     }
01335 
01336     // Force memory to be reclaimed.
01337     d_compound_buf.resize(0);
01338     d_str.resize(0);
01339 
01340     d_capacity = 0;
01341     set_read_p(false);
01342 }
01343 
01351 unsigned int Vector::get_value_capacity() const
01352 {
01353     return d_capacity;
01354 }
01355 
01365 void Vector::reserve_value_capacity(unsigned int numElements)
01366 {
01367     if (!d_proto) {
01368         throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Logic error: _var is null!");
01369     }
01370     switch (d_proto->type()) {
01371         case dods_byte_c:
01372         case dods_char_c:
01373         case dods_int8_c:
01374         case dods_uint8_c:
01375         case dods_int16_c:
01376         case dods_uint16_c:
01377         case dods_int32_c:
01378         case dods_uint32_c:
01379         case dods_int64_c:
01380         case dods_uint64_c:
01381 
01382         case dods_enum_c:
01383 
01384         case dods_float32_c:
01385         case dods_float64_c:
01386             // Make _buf be the right size and set _capacity
01387             m_create_cardinal_data_buffer_for_type(numElements);
01388             break;
01389 
01390         case dods_str_c:
01391         case dods_url_c:
01392             // Make sure the d_str has enough room for all the strings.
01393             // Technically not needed, but it will speed things up for large arrays.
01394             d_str.reserve(numElements);
01395             d_capacity = numElements;
01396             break;
01397 
01398         case dods_array_c:
01399             throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Arrays not supported!");
01400             break;
01401 
01402         case dods_opaque_c:
01403         case dods_structure_c:
01404         case dods_sequence_c:
01405         case dods_grid_c:
01406             // not clear anyone will go this path, but best to be complete.
01407             d_compound_buf.reserve(numElements);
01408             d_capacity = numElements;
01409             break;
01410 
01411         default:
01412             throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
01413             break;
01414 
01415     } // switch
01416 
01417 }
01418 
01424 void Vector::reserve_value_capacity()
01425 {
01426     // Use the current length of the vector as the reserve amount.
01427     reserve_value_capacity(length());
01428 }
01429 
01458 unsigned int
01459 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
01460 {
01461         static const string funcName = "set_value_slice_from_row_major_vector:";
01462 
01463         // semantically const from the caller's viewpoint, but some calls are not syntactic const.
01464         Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
01465 
01466         bool typesMatch = rowMajorData.var() && d_proto && (rowMajorData.var()->type() == d_proto->type());
01467         if (!typesMatch) {
01468                 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: types do not match so cannot be copied!");
01469         }
01470 
01471         // Make sure the data exists
01472         if (!rowMajorData.read_p()) {
01473                 throw InternalErr(__FILE__, __LINE__,
01474                                 funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
01475         }
01476 
01477         // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
01478         if (rowMajorData.length() < 0) {
01479                 throw InternalErr(__FILE__, __LINE__,
01480                                 funcName
01481                                                 + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
01482         }
01483 
01484         // The read-in capacity had better be at least the length (the amount we will copy) or we'll memcpy into bad memory
01485         // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
01486         if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
01487                 throw InternalErr(__FILE__, __LINE__,
01488                                 funcName
01489                                                 + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
01490         }
01491 
01492         // Make sure there's enough room in this Vector to store all the elements requested.  Again,
01493         // better to throw than just copy what we can since it implies a logic error that needs to be solved.
01494         if (d_capacity < (startElement + rowMajorData.length())) {
01495                 throw InternalErr(__FILE__, __LINE__,
01496                                 funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
01497         }
01498 
01499         // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
01500         switch (d_proto->type()) {
01501                 case dods_int8_c:
01502                 case dods_uint8_c:
01503                 case dods_byte_c:
01504         case dods_char_c:
01505                 case dods_int16_c:
01506                 case dods_uint16_c:
01507                 case dods_int32_c:
01508                 case dods_uint32_c:
01509                 case dods_int64_c:
01510                 case dods_uint64_c:
01511 
01512                 case dods_enum_c:
01513 
01514                 case dods_float32_c:
01515                 case dods_float64_c: {
01516                         if (!d_buf) {
01517                                 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
01518                         }
01519                         if (!rowMajorData.d_buf) {
01520                                 throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
01521                         }
01522                         // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
01523                         int varWidth = d_proto->width();
01524                         char* pFromBuf = rowMajorData.d_buf;
01525                         int numBytesToCopy = rowMajorData.width(true);
01526                         char* pIntoBuf = d_buf + (startElement * varWidth);
01527                         memcpy(pIntoBuf, pFromBuf, numBytesToCopy);
01528                         break;
01529                 }
01530 
01531                 case dods_str_c:
01532                 case dods_url_c:
01533                         // Strings need to be copied directly
01534                         for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
01535                                 d_str[startElement + i] = rowMajorData.d_str[i];
01536                         }
01537                         break;
01538 
01539                 case dods_array_c:
01540         case dods_opaque_c:
01541                 case dods_structure_c:
01542                 case dods_sequence_c:
01543                 case dods_grid_c:
01544                         // Not sure that this function will be used for these type of nested objects, so I will throw here.
01545                         throw InternalErr(__FILE__, __LINE__,
01546                                         funcName + "Unimplemented method for Vectors of type: array, opaque, structure, sequence or grid.");
01547                         break;
01548 
01549                 default:
01550                         throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
01551                         break;
01552 
01553         } // switch (_var->type())
01554 
01555         // This is how many elements we copied.
01556         return (unsigned int) rowMajorData.length();
01557 }
01558 
01567 template <typename T>
01568 static bool types_match(Type t, T *cpp_var)
01569 {
01570     switch (t) {
01571     case dods_byte_c:
01572     case dods_char_c:
01573     case dods_uint8_c:
01574         return typeid(cpp_var) == typeid(dods_byte*);
01575 
01576     case dods_int8_c:
01577         return typeid(cpp_var) == typeid(dods_int8*);
01578     case dods_int16_c:
01579         return typeid(cpp_var) == typeid(dods_int16*);
01580     case dods_uint16_c:
01581         return typeid(cpp_var) == typeid(dods_uint16*);
01582     case dods_int32_c:
01583         return typeid(cpp_var) == typeid(dods_int32*);
01584     case dods_uint32_c:
01585         return typeid(cpp_var) == typeid(dods_uint32*);
01586     case dods_int64_c:
01587         return typeid(cpp_var) == typeid(dods_int64*);
01588     case dods_uint64_c:
01589         return typeid(cpp_var) == typeid(dods_uint64*);
01590 
01591     case dods_float32_c:
01592         return typeid(cpp_var) == typeid(dods_float32*);
01593     case dods_float64_c:
01594         return typeid(cpp_var) == typeid(dods_float64*);
01595 
01596     case dods_null_c:
01597     case dods_enum_c:
01598     case dods_str_c:
01599     case dods_url_c:
01600     case dods_opaque_c:
01601     case dods_array_c:
01602     case dods_structure_c:
01603     case dods_sequence_c:
01604     case dods_group_c:
01605     default:
01606         return false;
01607     }
01608 }
01609 
01611 
01613 template <typename T>
01614 bool Vector::set_value_worker(T *v, int sz)
01615 {
01616     if (!v || !types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
01617         return false;
01618 
01619     m_set_cardinal_values_internal(v, sz);
01620     return true;
01621 }
01622 
01623 bool Vector::set_value(dods_byte *val, int sz)
01624 {
01625     return set_value_worker(val, sz);
01626 }
01627 bool Vector::set_value(dods_int8 *val, int sz)
01628 {
01629     return set_value_worker(val, sz);
01630 }
01631 bool Vector::set_value(dods_int16 *val, int sz)
01632 {
01633     return set_value_worker(val, sz);
01634 }
01635 bool Vector::set_value(dods_uint16 *val, int sz)
01636 {
01637     return set_value_worker(val, sz);
01638 }
01639 bool Vector::set_value(dods_int32 *val, int sz)
01640 {
01641     return set_value_worker(val, sz);
01642 }
01643 bool Vector::set_value(dods_uint32 *val, int sz)
01644 {
01645     return set_value_worker(val, sz);
01646 }
01647 bool Vector::set_value(dods_int64 *val, int sz)
01648 {
01649     return set_value_worker(val, sz);
01650 }
01651 bool Vector::set_value(dods_uint64 *val, int sz)
01652 {
01653     return set_value_worker(val, sz);
01654 }
01655 bool Vector::set_value(dods_float32 *val, int sz)
01656 {
01657     return set_value_worker(val, sz);
01658 }
01659 bool Vector::set_value(dods_float64 *val, int sz)
01660 {
01661     return set_value_worker(val, sz);
01662 }
01663 
01665 bool Vector::set_value(string *val, int sz)
01666 {
01667     if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
01668         d_str.resize(sz);
01669         d_capacity = sz;
01670         for (register int t = 0; t < sz; t++) {
01671             d_str[t] = val[t];
01672         }
01673         set_length(sz);
01674         set_read_p(true);
01675         return true;
01676     }
01677     else {
01678         return false;
01679     }
01680 }
01681 
01682 template<typename T>
01683 bool Vector::set_value_worker(vector<T> &v, int sz)
01684 {
01685     return set_value(&v[0], sz);
01686 }
01687 
01688 bool Vector::set_value(vector<dods_byte> &val, int sz)
01689 {
01690     return set_value_worker(val, sz);
01691 }
01692 bool Vector::set_value(vector<dods_int8> &val, int sz)
01693 {
01694     return set_value_worker(val, sz);
01695 }
01696 bool Vector::set_value(vector<dods_int16> &val, int sz)
01697 {
01698     return set_value_worker(val, sz);
01699 }
01700 bool Vector::set_value(vector<dods_uint16> &val, int sz)
01701 {
01702     return set_value_worker(val, sz);
01703 }
01704 bool Vector::set_value(vector<dods_int32> &val, int sz)
01705 {
01706     return set_value_worker(val, sz);
01707 }
01708 bool Vector::set_value(vector<dods_uint32> &val, int sz)
01709 {
01710     return set_value_worker(val, sz);
01711 }
01712 bool Vector::set_value(vector<dods_int64> &val, int sz)
01713 {
01714     return set_value_worker(val, sz);
01715 }
01716 bool Vector::set_value(vector<dods_uint64> &val, int sz)
01717 {
01718     return set_value_worker(val, sz);
01719 }
01720 bool Vector::set_value(vector<dods_float32> &val, int sz)
01721 {
01722     return set_value_worker(val, sz);
01723 }
01724 bool Vector::set_value(vector<dods_float64> &val, int sz)
01725 {
01726     return set_value_worker(val, sz);
01727 }
01728 
01729 
01731 bool Vector::set_value(vector<string> &val, int sz)
01732 {
01733     if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
01734         d_str.resize(sz);
01735         d_capacity = sz;
01736         for (register int t = 0; t < sz; t++) {
01737             d_str[t] = val[t];
01738         }
01739         set_length(sz);
01740         set_read_p(true);
01741         return true;
01742     }
01743     else {
01744         return false;
01745     }
01746 }
01748 
01750 
01767 template <typename T>
01768 void Vector::value_worker(vector<unsigned int> *indices, T *b) const
01769 {
01770    // unsigned long currentIndex;
01771 #if 0
01772     // Iterator version. Not tested, jhrg 8/14/13
01773     for (vector<unsigned int>::iterator i = indices->begin(), e = indices->end(); i != e; ++i) {
01774         unsigned long currentIndex = *i;
01775         if(currentIndex > (unsigned int)length()){
01776             stringstream s;
01777             s << "Vector::value() - Subset index[" << i - subsetIndex->begin() <<  "] = " << currentIndex << " references a value that is " <<
01778                     "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
01779             throw Error(s.str());
01780         }
01781         b[i - indices->begin()] = reinterpret_cast<T*>(d_buf )[currentIndex];
01782     }
01783 #endif
01784     for (unsigned long i = 0, e = indices->size(); i < e; ++i) {
01785         unsigned long currentIndex = (*indices)[i];
01786         if (currentIndex > (unsigned int)length()) {
01787             stringstream s;
01788             s << "Vector::value() - Subset index[" << i <<  "] = " << currentIndex << " references a value that is " <<
01789                     "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
01790             throw Error(s.str());
01791         }
01792         b[i] = reinterpret_cast<T*>(d_buf )[currentIndex]; // I like this version - and it works!
01793     }
01794 }
01795 void Vector::value(vector<unsigned int> *indices, dods_byte *b) const    { value_worker(indices, b); }
01796 void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const    { value_worker(indices, b); }
01797 void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const   { value_worker(indices, b); }
01798 void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const  { value_worker(indices, b); }
01799 void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const   { value_worker(indices, b); }
01800 void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const  { value_worker(indices, b); }
01801 void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const   { value_worker(indices, b); }
01802 void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const  { value_worker(indices, b); }
01803 void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const { value_worker(indices, b); }
01804 void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const { value_worker(indices, b); }
01805 
01806 #if 0
01807 template void Vector::value(vector<unsigned int> *indices, dods_byte *b) const;
01808 template void Vector::value(vector<unsigned int> *indices, dods_int8 *b) const;
01809 template void Vector::value(vector<unsigned int> *indices, dods_int16 *b) const;
01810 template void Vector::value(vector<unsigned int> *indices, dods_uint16 *b) const;
01811 template void Vector::value(vector<unsigned int> *indices, dods_int32 *b) const;
01812 template void Vector::value(vector<unsigned int> *indices, dods_uint32 *b) const;
01813 template void Vector::value(vector<unsigned int> *indices, dods_int64 *b) const;
01814 template void Vector::value(vector<unsigned int> *indices, dods_uint64 *b) const;
01815 template void Vector::value(vector<unsigned int> *indices, dods_float32 *b) const;
01816 template void Vector::value(vector<unsigned int> *indices, dods_float64 *b) const;
01817 #endif
01818 
01820 void Vector::value(vector<unsigned int> *subsetIndex, vector<string> &b) const
01821 {
01822     unsigned long currentIndex;
01823 
01824     if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c){
01825         for(unsigned long i=0; i<subsetIndex->size() ;++i){
01826             currentIndex = (*subsetIndex)[i] ;
01827             if(currentIndex > (unsigned int)length()){
01828                 stringstream s;
01829                 s << "Vector::value() - Subset index[" << i <<  "] = " << currentIndex << " references a value that is " <<
01830                         "outside the bounds of the internal storage [ length()= " << length() << " ] name: '" << name() << "'. ";
01831                 throw Error(s.str());
01832             }
01833             b[i] = d_str[currentIndex];
01834         }
01835     }
01836 }
01837 
01838 template <typename T>
01839 void Vector::value_worker(T *v) const
01840 {
01841     // Only copy if v is not null and the proto's  type matches.
01842     // For Enums, use the element type since type == dods_enum_c.
01843     if (v && types_match(d_proto->type() == dods_enum_c ? static_cast<D4Enum*>(d_proto)->element_type() : d_proto->type(), v))
01844         memcpy(v, d_buf, length() * sizeof(T));
01845 }
01846 void Vector::value(dods_byte *b) const    { value_worker(b); }
01847 void Vector::value(dods_int8 *b) const    { value_worker(b); }
01848 void Vector::value(dods_int16 *b) const   { value_worker(b); }
01849 void Vector::value(dods_uint16 *b) const  { value_worker(b); }
01850 void Vector::value(dods_int32 *b) const   { value_worker(b); }
01851 void Vector::value(dods_uint32 *b) const  { value_worker(b); }
01852 void Vector::value(dods_int64 *b) const   { value_worker(b); }
01853 void Vector::value(dods_uint64 *b) const  { value_worker(b); }
01854 void Vector::value(dods_float32 *b) const { value_worker(b); }
01855 void Vector::value(dods_float64 *b) const { value_worker(b); }
01856 
01857 #if 0
01858 template void Vector::value(dods_byte *v) const;
01859 template void Vector::value(dods_int8 *v) const;
01860 template void Vector::value(dods_int16 *v) const;
01861 template void Vector::value(dods_uint16 *v) const;
01862 template void Vector::value(dods_int32 *v) const;
01863 template void Vector::value(dods_uint32 *v) const;
01864 template void Vector::value(dods_int64 *v) const;
01865 template void Vector::value(dods_uint64 *v) const;
01866 template void Vector::value(dods_float32 *v) const;
01867 template void Vector::value(dods_float64 *v) const;
01868 #endif
01869 
01870 
01872 void Vector::value(vector<string> &b) const
01873 {
01874     if (d_proto->type() == dods_str_c || d_proto->type() == dods_url_c)
01875         b = d_str;
01876 }
01877 
01880 void *Vector::value()
01881 {
01882     void *buffer = new char[width(true)];
01883 
01884     memcpy(buffer, d_buf, width(true));
01885 
01886     return buffer;
01887 }
01889 
01905 void Vector::add_var(BaseType * v, Part /*p*/)
01906 {
01907 #if 0
01908         // Why doesn't this work?  tried all 3 variants. jhrg 8/14/13
01909         Vector::add_var_nocopy(v->ptr_duplicate(), p);
01910         add_var_nocopy(v->ptr_duplicate(), p);
01911         add_var_nocopy(v->ptr_duplicate());
01912 #else
01913         // Delete the current template variable
01914     if (d_proto) {
01915         delete d_proto;
01916         d_proto = 0;
01917     }
01918 
01919     // if 'v' is null, just set _var to null and exit.
01920     if (!v) {
01921         d_proto = 0;
01922     }
01923     else {
01924         // Jose Garcia
01925         // By getting a copy of this object to be assigned to _var
01926         // we let the owner of 'v' to deallocate it as necessary.
01927         d_proto = v->ptr_duplicate();
01928 
01929         // If 'v' has a name, use it as the name of the array. If v doesn't have
01930         // a name, then make sure to copy the array's name to it
01931         // so that software which uses the template's name will still work.
01932         if (!v->name().empty())
01933             set_name(v->name());
01934         else
01935             d_proto->set_name(name());
01936 
01937         d_proto->set_parent(this); // Vector --> child
01938 
01939         DBG(cerr << "Vector::add_var: Added variable " << v << " ("
01940                 << v->name() << " " << v->type_name() << ")" << endl);
01941     }
01942 #endif
01943 }
01944 
01945 void Vector::add_var_nocopy(BaseType * v, Part)
01946 {
01947         // Delete the current template variable
01948     if (d_proto) {
01949         delete d_proto;
01950         d_proto = 0;
01951     }
01952 
01953     // if 'v' is null, just set _var to null and exit.
01954     if (!v) {
01955         d_proto = 0;
01956     }
01957     else {
01958         d_proto = v;
01959 
01960         // If 'v' has a name, use it as the name of the array. If it *is*
01961         // empty, then make sure to copy the array's name to the template
01962         // so that software which uses the template's name will still work.
01963         if (!v->name().empty())
01964             set_name(v->name());
01965         else
01966             d_proto->set_name(name());
01967 
01968         d_proto->set_parent(this); // Vector is the parent; proto is the child
01969 
01970         DBG(cerr << "Vector::add_var_no_copy: Added variable " << v << " ("
01971                 << v->name() << " " << v->type_name() << ")" << endl);
01972     }
01973 }
01974 
01975 bool Vector::check_semantics(string & msg, bool)
01976 {
01977     return BaseType::check_semantics(msg);
01978 }
01979 
01988 void Vector::dump(ostream &strm) const
01989 {
01990     strm << DapIndent::LMarg << "Vector::dump - (" << (void *) this << ")" << endl;
01991     DapIndent::Indent();
01992     BaseType::dump(strm);
01993     strm << DapIndent::LMarg << "# elements in vector: " << d_length << endl;
01994     if (d_proto) {
01995         strm << DapIndent::LMarg << "base type:" << endl;
01996         DapIndent::Indent();
01997         d_proto->dump(strm);
01998         DapIndent::UnIndent();
01999     }
02000     else {
02001         strm << DapIndent::LMarg << "base type: not set" << endl;
02002     }
02003     strm << DapIndent::LMarg << "vector contents:" << endl;
02004     DapIndent::Indent();
02005     for (unsigned i = 0; i < d_compound_buf.size(); ++i) {
02006         if (d_compound_buf[i])
02007             d_compound_buf[i]->dump(strm);
02008         else
02009             strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl;
02010     }
02011     DapIndent::UnIndent();
02012     strm << DapIndent::LMarg << "strings:" << endl;
02013     DapIndent::Indent();
02014     for (unsigned i = 0; i < d_str.size(); i++) {
02015         strm << DapIndent::LMarg << d_str[i] << endl;
02016     }
02017     DapIndent::UnIndent();
02018     if (d_buf) {
02019         switch (d_proto != 0 ? d_proto->type() : 0) {
02020             case dods_byte_c:
02021             case dods_char_c:
02022                 strm << DapIndent::LMarg << "_buf: ";
02023                 strm.write(d_buf, d_length);
02024                 strm << endl;
02025                 break;
02026 
02027             case 0:
02028             default:
02029                 strm << DapIndent::LMarg << "_buf: " << (void *) d_buf << endl;
02030                 break;
02031         }
02032     }
02033     else {
02034         strm << DapIndent::LMarg << "_buf: EMPTY" << endl;
02035     }
02036 
02037     DapIndent::UnIndent();
02038 }
02039 
02040 } // namespace libdap
02041