libdap++ Updated for version 3.8.2

Vector.cc

Go to the documentation of this file.
00001 
00002 // -*- mode: c++; c-basic-offset:4 -*-
00003 
00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00005 // Access Protocol.
00006 
00007 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00008 // Author: James Gallagher <jgallagher@opendap.org>
00009 //
00010 // This library is free software; you can redistribute it and/or
00011 // modify it under the terms of the GNU Lesser General Public
00012 // License as published by the Free Software Foundation; either
00013 // version 2.1 of the License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 //
00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00025 
00026 // (c) COPYRIGHT URI/MIT 1995-1999
00027 // Please read the full copyright statement in the file COPYRIGHT_URI.
00028 //
00029 // Authors:
00030 //      jhrg,jimg       James Gallagher <jgallagher@gso.uri.edu>
00031 
00032 // Implementation for class Vector. This class is the basis for all the
00033 // vector-type classes in libdap's <Array, List>.
00034 //
00035 // 11/21/95 jhrg
00036 
00037 #include "config.h"
00038 
00039 #include <cstring>
00040 
00041 static char rcsid[] not_used =
00042     { "$Id: Vector.cc 21976 2010-01-12 17:16:22Z jimg $"
00043     };
00044 
00045 //#define DODS_DEBUG
00046 
00047 #include <algorithm>
00048 
00049 #include "Vector.h"
00050 #include "escaping.h"
00051 #include "util.h"
00052 #include "debug.h"
00053 #include "InternalErr.h"
00054 #include <sstream>
00055 
00056 using std::cerr;
00057 using std::endl;
00058 
00059 namespace libdap {
00060 
00061 void Vector::_duplicate(const Vector & v)
00062 {
00063     _length = v._length;
00064 
00065     // _var holds the type of the elements. That is, it holds a BaseType
00066     // which acts as a template for the type of each element.
00067     if (v._var) {
00068         _var = v._var->ptr_duplicate(); // use ptr_duplicate()
00069         _var->set_parent(this); // ptr_duplicate does not set d_parent.
00070     }
00071     else {
00072         _var = 0;
00073     }
00074 
00075     // _vec and _buf (further down) hold the values of the Vector. The field
00076     // _vec is used when the Vector holds non-numeric data (including strings
00077     // although it used to be that was not the case jhrg 2/10/05) while _buf
00078     // holds numeric values.
00079     if (v._vec.empty()) {
00080         _vec = v._vec;
00081     }
00082     else {
00083         // Failure to set the size will make the [] operator barf on the LHS
00084         // of the assignment inside the loop.
00085         _vec.resize(_length);
00086         for (int i = 0; i < _length; ++i) {
00087             // There's no need to call set_parent() for each element; we
00088             // maintain the back pointer using the _var member. These
00089             // instances are used to hold _values_ only while the _var
00090             // field holds the type of the elements.
00091             _vec[i] = v._vec[i]->ptr_duplicate();
00092         }
00093     }
00094 
00095     // copy the strings. This copies the values.
00096     d_str = v.d_str;
00097 
00098     // copy numeric values if there are any.
00099     _buf = 0;                   // init to null
00100     if (v._buf)                 // only copy if data present
00101         val2buf(v._buf);        // store v's value in this's _BUF.
00102 
00103     _capacity = v._capacity;
00104 }
00105 
00110 bool
00111 Vector::is_cardinal_type() const
00112 {
00113   // Not cardinal if no _var at all!
00114   if (!_var) {
00115     return false;
00116   }
00117 
00118   switch (_var->type()) {
00119      case dods_byte_c:
00120      case dods_int16_c:
00121      case dods_uint16_c:
00122      case dods_int32_c:
00123      case dods_uint32_c:
00124      case dods_float32_c:
00125      case dods_float64_c: {
00126        return true;
00127        break;
00128      }
00129 
00130      // These must be handled differently.
00131      case dods_str_c:
00132      case dods_url_c:
00133      case dods_array_c:
00134      case dods_structure_c:
00135      case dods_sequence_c:
00136      case dods_grid_c:
00137        return false;
00138        break;
00139 
00140      default:
00141        cerr << "Vector::var: Unrecognized type" << endl;
00142        return false;
00143   } // switch
00144 }
00145 
00158 unsigned int
00159 Vector::create_cardinal_data_buffer_for_type(unsigned int numEltsOfType)
00160 {
00161   // Make sure we HAVE a _var, or we cannot continue.
00162   if (!_var) {
00163     throw InternalErr(__FILE__, __LINE__,
00164         "create_cardinal_data_buffer_for_type: Logic error: _var is null!");
00165   }
00166 
00167   // Make sure we only do this for the correct data types.
00168   if (!is_cardinal_type()) {
00169       throw InternalErr(__FILE__, __LINE__,
00170           "create_cardinal_data_buffer_for_type: incorrectly used on Vector whose type was not a cardinal (simple data types).");
00171   }
00172 
00173   delete_cardinal_data_buffer();
00174 
00175   // Actually new up the array with enough bytes to hold numEltsOfType of the actual type.
00176   unsigned int bytesPerElt = _var->width();
00177   unsigned int bytesNeeded = bytesPerElt * numEltsOfType;
00178   _buf = new char[bytesNeeded];
00179   if (!_buf) {
00180     ostringstream oss;
00181     oss << "create_cardinal_data_buffer_for_type: new char[] failed to allocate " <<
00182            bytesNeeded <<
00183            " bytes!  Out of memory or too large a buffer required!";
00184     throw InternalErr(__FILE__, __LINE__, oss.str());
00185   }
00186   _capacity = numEltsOfType;
00187   return bytesNeeded;
00188 }
00189 
00191 void
00192 Vector::delete_cardinal_data_buffer()
00193 {
00194   if (_buf) {
00195      delete[] _buf;
00196      _buf = 0;
00197      _capacity = 0;
00198    }
00199 }
00200 
00204 template <class CardType>
00205 void
00206 Vector::set_cardinal_values_internal(const CardType* fromArray, int numElts)
00207 {
00208   if (numElts < 0) {
00209      throw InternalErr(__FILE__, __LINE__,
00210                  "Logic error: Vector::set_cardinal_values_internal() called with negative numElts!");
00211   }
00212   if (!fromArray) {
00213     throw InternalErr(__FILE__, __LINE__,
00214         "Logic error: Vector::set_cardinal_values_internal() called with null fromArray!");
00215   }
00216   set_length(numElts);
00217   create_cardinal_data_buffer_for_type(numElts);
00218   memcpy(_buf, fromArray, numElts * sizeof(CardType) );
00219   set_read_p(true);
00220 }
00221 
00222 
00239 Vector::Vector(const string & n, BaseType * v, const Type & t)
00240         : BaseType(n, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
00241 {
00242     if (v)
00243         add_var(v);
00244 
00245     DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
00246     if (_var)
00247         _var->set_parent(this);
00248 }
00249 
00269 Vector::Vector(const string & n, const string &d, BaseType * v, const Type & t)
00270         : BaseType(n, d, t), _length(-1), _var(0), _buf(0), _vec(0), _capacity(0)
00271 {
00272     if (v)
00273         add_var(v);
00274 
00275     DBG2(cerr << "Entering Vector ctor for object: " << this << endl);
00276     if (_var)
00277         _var->set_parent(this);
00278 }
00279 
00281 Vector::Vector(const Vector & rhs): BaseType(rhs)
00282 {
00283     DBG2(cerr << "Entering Vector const ctor for object: " << this <<
00284          endl);
00285     DBG2(cerr << "RHS: " << &rhs << endl);
00286 
00287     _duplicate(rhs);
00288 }
00289 
00290 Vector::~Vector()
00291 {
00292     DBG2(cerr << "Entering ~Vector (" << this << ")" << endl);
00293 
00294     delete _var;
00295     _var = 0;
00296 
00297     // Clears all buffers
00298     clear_local_data();
00299 
00300     DBG2(cerr << "Exiting ~Vector" << endl);
00301 }
00302 
00303 Vector & Vector::operator=(const Vector & rhs)
00304 {
00305     if (this == &rhs)
00306         return *this;
00307 
00308     dynamic_cast < BaseType & >(*this) = rhs;
00309 
00310     _duplicate(rhs);
00311 
00312     return *this;
00313 }
00314 
00315 void
00316 Vector::set_name(const std::string& name)
00317 {
00318   BaseType::set_name(name);
00319   // We need to set the template variable name as well since
00320   // this is what gets output in the dds!  Otherwise, there's a mismatch.
00321   if (_var) {
00322       _var->set_name(name);
00323   }
00324 }
00325 
00326 int Vector::element_count(bool leaves)
00327 {
00328     if (!leaves)
00329         return 1;
00330     else
00331         // var() only works for simple types!
00332         return var(0)->element_count(leaves);
00333 }
00334 
00335 // These mfuncs set the _send_p and _read_p fields of BaseType. They differ
00336 // from BaseType's version in that they set both the Vector object's copy of
00337 // _send_p (_read_p) but also _VAR's copy. This does not matter much when _VAR
00338 // is a scalar, but does matter when it is an aggregate.
00339 
00346 void Vector::set_send_p(bool state)
00347 {
00348     _var->set_send_p(state);
00349     BaseType::set_send_p(state);
00350 }
00351 
00358 void Vector::set_read_p(bool state)
00359 {
00360     if (_var) {
00361       _var->set_read_p(state);
00362     }
00363     BaseType::set_read_p(state);
00364 }
00365 
00383 BaseType *Vector::var(const string & n, bool exact, btp_stack * s)
00384 {
00385     string name = www2id(n);
00386     DBG(cerr << "Vector::var: Looking for " << n << endl);
00387 
00388     // Make sure to check for the case where name is the default (the empty
00389     // string). 9/1/98 jhrg
00390     if (_var->is_constructor_type()) {
00391         if (name == "" || _var->name() == name) {
00392             if (s)
00393                 s->push(this);
00394             return _var;
00395         }
00396         else {
00397             BaseType * result = _var->var(name, exact, s);
00398             if (result && s)
00399                 s->push(this);
00400             return result;
00401         }
00402     }
00403     else {
00404         return _var; // I don't see why this isn't return 0 *** jhrg 10/9/08
00405     }
00406 }
00407 
00418 BaseType *Vector::var(const string & n, btp_stack & s)
00419 {
00420     string name = www2id(n);
00421 
00422     if (_var->is_constructor_type())
00423         return _var->var(name, s);
00424     else {
00425         s.push((BaseType *) this);
00426         return _var;
00427     }
00428 }
00429 
00430 // Return a pointer the the BaseType object for element I. If the Vector is
00431 // of a cardinal type, store the ith element's value in the BaseType
00432 // object. If it is a Vector of a non-cardinal type, then this mfunc returns
00433 // _vec[i].
00434 //
00435 // NB: I defaults to zero.
00436 //
00437 // Returns: A BaseType pointer to the ith element of the Vector.
00438 
00454 BaseType *Vector::var(unsigned int i)
00455 {
00456 
00457     switch (_var->type()) {
00458     case dods_byte_c:
00459     case dods_int16_c:
00460     case dods_uint16_c:
00461     case dods_int32_c:
00462     case dods_uint32_c:
00463     case dods_float32_c:
00464     case dods_float64_c: {
00465             // Transfer the ith value to the BaseType *_var; There are more
00466             // efficient ways to get a whole array using buf2val() but this is
00467             // an OK way to get a single value or several non-contiguous values.
00468             unsigned int sz = _var->width();
00469             _var->val2buf((char *) _buf + (i * sz));
00470             return _var;
00471             break;
00472         }
00473 
00474     case dods_str_c:
00475     case dods_url_c:
00476         _var->val2buf(&d_str[i]);
00477         return _var;
00478         break;
00479 
00480     case dods_array_c:
00481     case dods_structure_c:
00482     case dods_sequence_c:
00483     case dods_grid_c:
00484         return _vec[i];
00485         break;
00486 
00487     default:
00488         cerr << "Vector::var: Unrecognized type" << endl;
00489     }
00490 
00491     return 0;
00492 }
00493 
00494 // Return: The number of bytes required to store the vector `in a C
00495 // program'. For an array of cardinal types this is the same as the storage
00496 // used by _BUF. For anything else, it is the product of length() and the
00497 // element width(). It turns out that both values can be computed the same
00498 // way.
00499 //
00500 // Returns: The number of bytes used to store the vector.
00501 
00507 unsigned int Vector::width()
00508 {
00509     // Jose Garcia
00510     if (!_var) {
00511         throw InternalErr(__FILE__, __LINE__,
00512                           "Cannot get width since *this* object is not holding data.");
00513     }
00514 
00515     return length() * _var->width();
00516 }
00517 
00518 // Returns: the number of elements in the vector.
00519 
00524 int Vector::length() const
00525 {
00526     return _length;
00527 }
00528 
00529 // set the number of elements in the vector.
00530 //
00531 // Returns: void
00532 
00535 void Vector::set_length(int l)
00536 {
00537     _length = l;
00538 }
00539 
00540 // \e l is the number of elements the vector can hold (e.g., if l == 20, then
00541 // the vector can hold elements 0, .., 19).
00542 
00548 void Vector::vec_resize(int l)
00549 {
00550     _vec.resize((l > 0) ? l : 0, 0);    // Fill with NULLs
00551     _capacity = l; // capacity in terms of number of elements.
00552 }
00553 
00569 void
00570 Vector::intern_data(ConstraintEvaluator &eval, DDS &dds)
00571 {
00572     DBG(cerr << "Vector::intern_data: " << name() << endl);
00573     if (!read_p())
00574         read();          // read() throws Error and InternalErr
00575 
00576     // length() is not capacity; it must be set explicitly in read().
00577     int num = length();
00578 
00579     switch (_var->type()) {
00580     case dods_byte_c:
00581     case dods_int16_c:
00582     case dods_uint16_c:
00583     case dods_int32_c:
00584     case dods_uint32_c:
00585     case dods_float32_c:
00586     case dods_float64_c:
00587         // For these cases, read() puts the data into _buf, which is what we
00588         // need to do 'stuff' with the data.
00589         break;
00590 
00591     case dods_str_c:
00592     case dods_url_c:
00593         // For these cases, read() will put the data into d_str[], which is
00594         // what the transformation classes need.
00595         break;
00596 
00597     case dods_array_c:
00598         // I think this is an error since there can never be an Array of
00599         // Array.
00600         throw InternalErr(__FILE__, __LINE__, "Array of Array not supported.");
00601         break;
00602 
00603     case dods_structure_c:
00604     case dods_sequence_c:
00605     case dods_grid_c:
00606         DBG(cerr << "Vector::intern_data: found ctor" << endl);
00607         // For these cases, we need to call read() for each of the 'num'
00608         // elements in the '_vec[]' array of BaseType object pointers.
00609         if (_vec.capacity() == 0)
00610             throw InternalErr(__FILE__, __LINE__,
00611                               "The capacity of *this* vector is 0.");
00612 
00613         for (int i = 0; i < num; ++i)
00614             _vec[i]->intern_data(eval, dds);
00615 
00616         break;
00617 
00618     default:
00619         throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
00620         break;
00621     }
00622 }
00623 
00636 bool Vector::serialize(ConstraintEvaluator & eval, DDS & dds,
00637                        Marshaller &m, bool ce_eval)
00638 {
00639     int i = 0;
00640 
00641     dds.timeout_on();
00642 
00643     if (!read_p())
00644         read();          // read() throws Error and InternalErr
00645 
00646 #if EVAL
00647     if (ce_eval && !eval.eval_selection(dds, dataset()))
00648         return true;
00649 #endif
00650 
00651     dds.timeout_off();
00652 
00653     // length() is not capacity; it must be set explicitly in read().
00654     int num = length();
00655 
00656     switch (_var->type()) {
00657     case dods_byte_c:
00658         m.put_vector( _buf, num, *this ) ;
00659         break ;
00660     case dods_int16_c:
00661     case dods_uint16_c:
00662     case dods_int32_c:
00663     case dods_uint32_c:
00664     case dods_float32_c:
00665     case dods_float64_c:
00666         m.put_vector( _buf, num, _var->width(), *this ) ;
00667         break;
00668 
00669     case dods_str_c:
00670     case dods_url_c:
00671         if (d_str.capacity() == 0)
00672             throw InternalErr(__FILE__, __LINE__,
00673                               "The capacity of the string vector is 0");
00674 
00675         m.put_int( num ) ;
00676 
00677         for (i = 0; i < num; ++i)
00678             m.put_str( d_str[i] ) ;
00679 
00680         break;
00681 
00682     case dods_array_c:
00683     case dods_structure_c:
00684     case dods_sequence_c:
00685     case dods_grid_c:
00686         //Jose Garcia
00687         // Not setting the capacity of _vec is an internal error.
00688         if (_vec.capacity() == 0)
00689             throw InternalErr(__FILE__, __LINE__,
00690                               "The capacity of *this* vector is 0.");
00691 
00692         m.put_int( num ) ;
00693 
00694         for (i = 0; i < num; ++i)
00695             _vec[i]->serialize(eval, dds, m, false);
00696 
00697         break;
00698 
00699     default:
00700         throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
00701         break;
00702     }
00703 
00704     return true;
00705 }
00706 
00707 // Read an object from the network and internalize it. For a Vector this is
00708 // handled differently for a `cardinal' type. Vectors of Cardinals are
00709 // stored using the `C' representations because these objects often are used
00710 // to build huge arrays (e.g., an array of 1024 by 1024 bytes). However,
00711 // arrays of non-cardinal types are stored as Vectors of the C++ objects or
00712 // DAP2 objects (Str and Url are vectors of the string class, Structure, ...,
00713 // Grid are vectors of the libdap Structure, ... classes).
00714 //
00715 // The boolean parameter REUSE determines whether internal storage is reused
00716 // or not. If true, the _buf member is assumed to be large enough to hold the
00717 // incoming cardinal data and is *not* reallocated. If false, new storage is
00718 // allocated. If the internal buffer has not yet been allocated, then this
00719 // parameter has no effect (i.e., storage is allocated). This parameter
00720 // effects storage for cardinal data only.
00721 //
00722 // Returns: True is successful, false otherwise.
00723 
00724 bool Vector::deserialize(UnMarshaller &um, DDS * dds, bool reuse)
00725 {
00726     unsigned int num;
00727     unsigned i = 0;
00728 
00729     switch (_var->type()) {
00730     case dods_byte_c:
00731     case dods_int16_c:
00732     case dods_uint16_c:
00733     case dods_int32_c:
00734     case dods_uint32_c:
00735     case dods_float32_c:
00736     case dods_float64_c:
00737         if (_buf && !reuse) {
00738             delete_cardinal_data_buffer();
00739         }
00740 
00741         um.get_int( (int &)num ) ;
00742 
00743         DBG(cerr << "Vector::deserialize: num = " << num << endl);
00744         DBG(cerr << "Vector::deserialize: length = " << length() << endl);
00745 
00746         if (length() == -1)
00747             set_length(num);
00748 
00749         if (num != (unsigned int) length())
00750             throw InternalErr(__FILE__, __LINE__, "The server sent declarations and data with mismatched sizes.");
00751 
00752         if (!_buf) {
00753             // Make _buf be large enough for length() elements of _var->type()
00754             create_cardinal_data_buffer_for_type(length());
00755             DBG(cerr << "Vector::deserialize: allocating "
00756                 << width() << " bytes for an array of "
00757                 << length() << " " << _var->type_name() << endl);
00758         }
00759 
00760         if (_var->type() == dods_byte_c)
00761             um.get_vector( (char **)&_buf, num, *this ) ;
00762         else
00763             um.get_vector( (char **)&_buf, num, _var->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__,
00778                               "The client sent declarations and data with mismatched sizes.");
00779 
00780         d_str.resize((num > 0) ? num : 0);      // Fill with NULLs
00781         _capacity = num; // capacity is number of strings we can fit.
00782 
00783         for (i = 0; i < num; ++i) {
00784             string str;
00785             um.get_str( str ) ;
00786             d_str[i] = str;
00787 
00788         }
00789 
00790         break;
00791 
00792     case dods_array_c:
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             _vec[i] = _var->ptr_duplicate();
00808             _vec[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 
00848 unsigned int Vector::val2buf(void *val, bool reuse)
00849 {
00850     // Jose Garcia
00851 
00852     // I *think* this method has been mainly designed to be use by read which
00853     // is implemented in the surrogate library. Passing NULL as a pointer to
00854     // this method will be an error of the creator of the surrogate library.
00855     // Even though I recognize the fact that some methods inside libdap++ can
00856     // call val2buf, I think by now no coding bugs such as misusing val2buf
00857     // will be in libdap++, so it will be an internal error from the
00858     // surrogate library.
00859     if (!val)
00860         throw InternalErr(__FILE__, __LINE__,
00861                           "The incoming pointer does not contain any data.");
00862 
00863     switch (_var->type()) {
00864     case dods_byte_c:
00865     case dods_int16_c:
00866     case dods_uint16_c:
00867     case dods_int32_c:
00868     case dods_uint32_c:
00869     case dods_float32_c:
00870     case dods_float64_c: {
00871             // width() returns the size given the constraint
00872             unsigned int array_wid = width();
00873             if (_buf && !reuse) {
00874                delete_cardinal_data_buffer();
00875             }
00876 
00877             if (!_buf) {        // First time or no reuse (free'd above)
00878               create_cardinal_data_buffer_for_type(length());
00879             }
00880 
00881             memcpy(_buf, val, array_wid);
00882             break;
00883         }
00884 
00885     case dods_str_c:
00886     case dods_url_c: {
00887             // Assume val points to an array of C++ string objects. Copy
00888             // them into the vector<string> field of this object.
00889             d_str.resize(_length);
00890             _capacity = _length;
00891             for (int i = 0; i < _length; ++i)
00892                 d_str[i] = *(static_cast < string * >(val) + i);
00893 
00894             break;
00895         }
00896 
00897     default:
00898         throw InternalErr(__FILE__, __LINE__, "Vector::val2buf: bad type");
00899 
00900     }
00901 
00902     return width();
00903 }
00904 
00935 unsigned int Vector::buf2val(void **val)
00936 {
00937     // Jose Garcia
00938     // The same comment in Vector::val2buf applies here!
00939     if (!val)
00940         throw InternalErr(__FILE__, __LINE__, "NULL pointer.");
00941 
00942     unsigned int wid = static_cast<unsigned int>(width());
00943     // This is the width computed using length(). The
00944     // length() property is changed when a projection
00945     // constraint is applied. Thus this is the number of
00946     // bytes in the buffer given the current constraint.
00947 
00948     switch (_var->type()) {
00949     case dods_byte_c:
00950     case dods_int16_c:
00951     case dods_uint16_c:
00952     case dods_int32_c:
00953     case dods_uint32_c:
00954     case dods_float32_c:
00955     case dods_float64_c:
00956         if (!*val) {
00957             *val = new char[wid];
00958         }
00959         // avoid bus error if _buf is null and this is called improperly.
00960         if (!_buf) {
00961           throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: Logic error: called when _buf was null!");
00962         }
00963 
00964         (void) memcpy(*val, _buf, wid);
00965 
00966         break;
00967 
00968     case dods_str_c:
00969     case dods_url_c: {
00970             if (!*val)
00971                 *val = new string[_length];
00972 
00973             for (int i = 0; i < _length; ++i)
00974                 *(static_cast < string * >(*val) + i) = d_str[i];
00975 
00976             break;
00977         }
00978 
00979     default:
00980         throw InternalErr(__FILE__, __LINE__, "Vector::buf2val: bad type");
00981         return 0;
00982     }
00983 
00984     return wid;
00985 }
00986 
01007 void Vector::set_vec(unsigned int i, BaseType * val)
01008 {
01009     // Jose Garcia
01010     // This is a public method which allows users to set the elements
01011     // of *this* vector. Passing an invalid index, a NULL pointer or
01012     // mismatching the vector type are internal errors.
01013     if (i >= static_cast < unsigned int >(_length))
01014         throw InternalErr(__FILE__, __LINE__,
01015                           "Invalid data: index too large.");
01016     if (!val)
01017         throw InternalErr(__FILE__, __LINE__,
01018                           "Invalid data: null pointer to BaseType object.");
01019     if (val->type() != _var->type())
01020         throw InternalErr(__FILE__, __LINE__,
01021                           "invalid data: type of incoming object does not match *this* vector type.");
01022 
01023     if (i >= _vec.capacity())
01024         vec_resize(i + 10);
01025 
01026     _vec[i] = val->ptr_duplicate();
01027 }
01028 
01038 void
01039 Vector::clear_local_data()
01040 {
01041   if (_buf) {
01042     delete[]_buf;
01043     _buf = 0;
01044   }
01045 
01046   for (unsigned int i = 0; i < _vec.size(); ++i) {
01047     delete _vec[i];
01048     _vec[i] = 0;
01049   }
01050 
01051   // Force memory to be reclaimed.
01052   _vec.resize(0);
01053   d_str.resize(0);
01054 
01055   _capacity = 0;
01056   set_read_p(false);
01057 }
01058 
01059 
01067 unsigned int
01068 Vector::get_value_capacity() const
01069 {
01070   return _capacity;
01071 }
01072 
01073 
01083 void
01084 Vector::reserve_value_capacity(unsigned int numElements)
01085 {
01086   if (!_var) {
01087    throw InternalErr(__FILE__, __LINE__,
01088        "reserve_value_capacity: Logic error: _var is null!");
01089   }
01090   switch (_var->type()) {
01091      case dods_byte_c:
01092      case dods_int16_c:
01093      case dods_uint16_c:
01094      case dods_int32_c:
01095      case dods_uint32_c:
01096      case dods_float32_c:
01097      case dods_float64_c: {
01098          // Make _buf be the right size and set _capacity
01099          create_cardinal_data_buffer_for_type(numElements);
01100        }
01101        break;
01102 
01103      case dods_str_c:
01104      case dods_url_c: {
01105          // Make sure the d_str has enough room for all the strings.
01106          // Technically not needed, but it will speed things up for large arrays.
01107          d_str.reserve(numElements);
01108          _capacity = numElements;
01109        }
01110        break;
01111 
01112 
01113      case dods_array_c:
01114      case dods_structure_c:
01115      case dods_sequence_c:
01116      case dods_grid_c: {
01117          // not clear anyone will go this path, but best to be complete.
01118          _vec.reserve(numElements);
01119          _capacity = numElements;
01120        }
01121       break;
01122 
01123      default: {
01124          throw InternalErr(__FILE__, __LINE__, "reserve_value_capacity: Unknown type!");
01125        }
01126      break;
01127 
01128   } // switch
01129 
01130 }
01131 
01137 void
01138 Vector::reserve_value_capacity()
01139 {
01140   // Use the current length of the vector as the reserve amount.
01141   reserve_value_capacity(length());
01142 }
01143 
01172 unsigned int
01173 Vector::set_value_slice_from_row_major_vector(const Vector& rowMajorDataC, unsigned int startElement)
01174 {
01175   static const string funcName = "set_value_slice_from_row_major_vector:";
01176 
01177   // semantically const from the caller's viewpoint, but some calls are not syntactic const.
01178   Vector& rowMajorData = const_cast<Vector&>(rowMajorDataC);
01179 
01180   bool typesMatch = rowMajorData.var() && _var && (rowMajorData.var()->type() == _var->type());
01181   if (!typesMatch) {
01182     throw InternalErr(__FILE__, __LINE__,
01183         funcName + "Logic error: types do not match so cannot be copied!");
01184   }
01185 
01186   // Make sure the data exists
01187   if (!rowMajorData.read_p()) {
01188     throw InternalErr(__FILE__, __LINE__,
01189         funcName + "Logic error: the Vector to copy data from has !read_p() and should have been read in!");
01190   }
01191 
01192   // Check this otherwise the static_cast<unsigned int> below will do the wrong thing.
01193   if (rowMajorData.length() < 0) {
01194     throw InternalErr(__FILE__, __LINE__,
01195             funcName + "Logic error: the Vector to copy data from has length() < 0 and was probably not initialized!");
01196   }
01197 
01198   // The read-in capacity had better be at least the length (the amountt we will copy) or we'll memcpy into bad memory
01199   // I imagine we could copy just the capacity rather than throw, but I really think this implies a problem to be addressed.
01200   if (rowMajorData.get_value_capacity() < static_cast<unsigned int>(rowMajorData.length())) {
01201     throw InternalErr(__FILE__, __LINE__,
01202         funcName + "Logic error: the Vector to copy from has a data capacity less than its length, can't copy!");
01203   }
01204 
01205   // Make sure there's enough room in this Vector to store all the elements requested.  Again,
01206   // better to throw than just copy what we can since it implies a logic error that needs to be solved.
01207   if (_capacity < (startElement + rowMajorData.length())) {
01208     throw InternalErr(__FILE__, __LINE__,
01209         funcName + "Logic error: the capacity of this Vector cannot hold all the data in the from Vector!");
01210   }
01211 
01212   // OK, at this point we're pretty sure we can copy the data, but we have to do it differently depending on type.
01213   switch (_var->type()) {
01214       case dods_byte_c:
01215       case dods_int16_c:
01216       case dods_uint16_c:
01217       case dods_int32_c:
01218       case dods_uint32_c:
01219       case dods_float32_c:
01220       case dods_float64_c: {
01221         if (!_buf) {
01222           throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: this->_buf was unexpectedly null!");
01223         }
01224         if (!rowMajorData._buf) {
01225           throw InternalErr(__FILE__, __LINE__, funcName + "Logic error: rowMajorData._buf was unexpectedly null!");
01226         }
01227         // memcpy the data into this, taking care to do ptr arithmetic on bytes and not sizeof(element)
01228         int varWidth = _var->width();
01229         char* pFromBuf = rowMajorData._buf;
01230         int numBytesToCopy = rowMajorData.width();
01231         char* pIntoBuf = _buf + (startElement * varWidth);
01232         memcpy(pIntoBuf,
01233                pFromBuf,
01234                numBytesToCopy );
01235       }
01236       break;
01237 
01238       case dods_str_c:
01239       case dods_url_c: {
01240         // Strings need to be copied directly
01241         for (unsigned int i = 0; i < static_cast<unsigned int>(rowMajorData.length()); ++i) {
01242           d_str[startElement + i] = rowMajorData.d_str[i];
01243         }
01244       }
01245       break;
01246 
01247       case dods_array_c:
01248       case dods_structure_c:
01249       case dods_sequence_c:
01250       case dods_grid_c: {
01251         // Not sure that this function will be used for these type of nested objects, so I will throw here.
01252         // TODO impl and test this path if it's ever needed.
01253         throw InternalErr(__FILE__, __LINE__,
01254             funcName + "Unimplemented method for Vectors of type: dods_array_c, dods_structure_c, dods_sequence_c and dods_grid_c.");
01255       }
01256       break;
01257 
01258       default: {
01259         throw InternalErr(__FILE__, __LINE__, funcName + ": Unknown type!");
01260       }
01261       break;
01262 
01263   } // switch (_var->type())
01264 
01265   // This is how many elements we copied.
01266   return (unsigned int)rowMajorData.length();
01267 }
01268 
01270 
01271 bool
01272 Vector::set_value(dods_byte *val, int sz)
01273 {
01274     if (var()->type() == dods_byte_c && val) {
01275       set_cardinal_values_internal<dods_byte>(val, sz);
01276       return true;
01277     }
01278     else {
01279         return false;
01280     }
01281 }
01282 
01284 bool
01285 Vector::set_value(vector<dods_byte> &val, int sz)
01286 {
01287     return set_value(&val[0], sz);
01288 }
01289 
01291 bool
01292 Vector::set_value(dods_int16 *val, int sz)
01293 {
01294     if (var()->type() == dods_int16_c && val) {
01295       set_cardinal_values_internal<dods_int16>(val, sz);
01296       return true;
01297     }
01298     else {
01299         return false;
01300     }
01301 }
01302 
01304 bool
01305 Vector::set_value(vector<dods_int16> &val, int sz)
01306 {
01307     return set_value(&val[0], sz);
01308 }
01309 
01311 bool
01312 Vector::set_value(dods_int32 *val, int sz)
01313 {
01314     if (var()->type() == dods_int32_c && val) {
01315        set_cardinal_values_internal<dods_int32>(val, sz);
01316        return true;
01317     }
01318     else {
01319         return false;
01320     }
01321 }
01322 
01324 bool
01325 Vector::set_value(vector<dods_int32> &val, int sz)
01326 {
01327     return set_value(&val[0], sz);
01328 }
01329 
01331 bool
01332 Vector::set_value(dods_uint16 *val, int sz)
01333 {
01334     if (var()->type() == dods_uint16_c && val) {
01335       set_cardinal_values_internal<dods_uint16>(val, sz);
01336       return true;
01337     }
01338     else {
01339         return false;
01340     }
01341 }
01342 
01344 bool
01345 Vector::set_value(vector<dods_uint16> &val, int sz)
01346 {
01347     return set_value(&val[0], sz);
01348 }
01349 
01351 bool
01352 Vector::set_value(dods_uint32 *val, int sz)
01353 {
01354     if (var()->type() == dods_uint32_c && val) {
01355         set_cardinal_values_internal<dods_uint32>(val, sz);
01356         return true;
01357     }
01358     else {
01359         return false;
01360     }
01361 }
01362 
01364 bool
01365 Vector::set_value(vector<dods_uint32> &val, int sz)
01366 {
01367     return set_value(&val[0], sz);
01368 }
01369 
01371 bool
01372 Vector::set_value(dods_float32 *val, int sz)
01373 {
01374     if (var()->type() == dods_float32_c && val) {
01375         set_cardinal_values_internal<dods_float32>(val, sz);
01376         return true;
01377     }
01378     else {
01379         return false;
01380     }
01381 }
01382 
01384 bool
01385 Vector::set_value(vector<dods_float32> &val, int sz)
01386 {
01387     return set_value(&val[0], sz);
01388 }
01389 
01391 bool
01392 Vector::set_value(dods_float64 *val, int sz)
01393 {
01394     if (var()->type() == dods_float64_c && val) {
01395       set_cardinal_values_internal<dods_float64>(val, sz);
01396       return true;
01397     }
01398     else {
01399       return false;
01400     }
01401 }
01402 
01404 bool
01405 Vector::set_value(vector<dods_float64> &val, int sz)
01406 {
01407     return set_value(&val[0], sz);
01408 }
01409 
01411 bool
01412 Vector::set_value(string *val, int sz)
01413 {
01414     if ((var()->type() == dods_str_c || var()->type() == dods_url_c) && val) {
01415         d_str.resize(sz);
01416         _capacity = sz;
01417         for (register int t = 0; t < sz; t++) {
01418             d_str[t] = val[t] ;
01419         }
01420         set_length(sz) ;
01421         set_read_p(true);
01422         return true;
01423     }
01424     else {
01425         return false;
01426     }
01427 }
01428 
01430 bool
01431 Vector::set_value(vector<string> &val, int sz)
01432 {
01433     if (var()->type() == dods_str_c || var()->type() == dods_url_c) {
01434         d_str.resize(sz);
01435         _capacity = sz;
01436         for (register int t = 0; t < sz; t++) {
01437             d_str[t] = val[t] ;
01438         }
01439         set_length(sz) ;
01440         set_read_p(true);
01441         return true;
01442     }
01443     else {
01444         return false;
01445     }
01446 }
01448 
01450 
01457 void Vector::value(dods_byte *b) const
01458 {
01459     if (b && _var->type() == dods_byte_c) {
01460         memcpy(b, _buf, length() * sizeof(dods_byte));
01461     }
01462 }
01463 
01465 void Vector::value(dods_uint16 *b) const
01466 {
01467     if (b && _var->type() == dods_uint16_c) {
01468         memcpy(b, _buf, length() * sizeof(dods_uint16));
01469     }
01470 }
01471 
01473 void Vector::value(dods_int16 *b) const
01474 {
01475     if (b && _var->type() == dods_int16_c) {
01476         memcpy(b, _buf, length() * sizeof(dods_int16));
01477     }
01478 }
01479 
01481 void Vector::value(dods_uint32 *b) const
01482 {
01483     if (b && _var->type() == dods_uint32_c) {
01484         memcpy(b, _buf, length() * sizeof(dods_uint32));
01485     }
01486 }
01487 
01489 void Vector::value(dods_int32 *b) const
01490 {
01491     if (b && _var->type() == dods_int32_c) {
01492         memcpy(b, _buf, length() * sizeof(dods_int32));
01493     }
01494 }
01495 
01497 void Vector::value(dods_float32 *b) const
01498 {
01499     if (b && _var->type() == dods_float32_c) {
01500         memcpy(b, _buf, length() * sizeof(dods_float32));
01501     }
01502 }
01503 
01505 void Vector::value(dods_float64 *b) const
01506 {
01507     if (b && _var->type() == dods_float64_c) {
01508         memcpy(b, _buf, length() * sizeof(dods_float64));
01509     }
01510 }
01511 
01513 void Vector::value(vector<string> &b) const
01514 {
01515     if (_var->type() == dods_byte_c || _var->type() == dods_url_c)
01516         b = d_str;
01517 }
01518 
01521 void *Vector::value()
01522 {
01523     void *buffer = new char[width()];
01524 
01525     memcpy(buffer, _buf, width());
01526 
01527     return buffer;
01528 }
01530 
01543 void Vector::add_var(BaseType * v, Part)
01544 {
01545     // Delete the current template variable
01546     if( _var )
01547     {
01548         delete _var;
01549         _var = 0 ;
01550     }
01551 
01552     // if 'v' is null, just set _var to null and exit.
01553     if (!v) {
01554         _var = 0;
01555     }
01556     else {
01557         // Jose Garcia
01558         // By getting a copy of this object to be assigned to _var
01559         // we let the owner of 'v' to deallocate it as necessary.
01560         _var = v->ptr_duplicate();
01561 
01562         // If 'v' has a name, use it as the name of the array. If it *is*
01563         // empty, then make sure to copy the array's name to the template
01564         // so that software which uses the template's name will still work.
01565         if (!v->name().empty())
01566             set_name(v->name());
01567         else
01568             _var->set_name(name());
01569 
01570         _var->set_parent(this); // Vector --> child
01571 
01572         DBG(cerr << "Vector::add_var: Added variable " << v << " ("
01573             << v->name() << " " << v->type_name() << ")" << endl);
01574     }
01575 }
01576 
01577 bool Vector::check_semantics(string & msg, bool)
01578 {
01579     return BaseType::check_semantics(msg);
01580 }
01581 
01590 void
01591 Vector::dump(ostream &strm) const
01592 {
01593     strm << DapIndent::LMarg << "Vector::dump - ("
01594     << (void *)this << ")" << endl ;
01595     DapIndent::Indent() ;
01596     BaseType::dump(strm) ;
01597     strm << DapIndent::LMarg << "# elements in vector: " << _length << endl ;
01598     if (_var) {
01599         strm << DapIndent::LMarg << "base type:" << endl ;
01600         DapIndent::Indent() ;
01601         _var->dump(strm) ;
01602         DapIndent::UnIndent() ;
01603     }
01604     else {
01605         strm << DapIndent::LMarg << "base type: not set" << endl ;
01606     }
01607     strm << DapIndent::LMarg << "vector contents:" << endl ;
01608     DapIndent::Indent() ;
01609     for (unsigned i = 0; i < _vec.size(); ++i) {
01610         if (_vec[i])
01611             _vec[i]->dump(strm) ;
01612         else
01613             strm << DapIndent::LMarg << "vec[" << i << "] is null" << endl ;
01614     }
01615     DapIndent::UnIndent() ;
01616     strm << DapIndent::LMarg << "strings:" << endl ;
01617     DapIndent::Indent() ;
01618     for (unsigned i = 0; i < d_str.size(); i++) {
01619         strm << DapIndent::LMarg << d_str[i] << endl ;
01620     }
01621     DapIndent::UnIndent() ;
01622     if( _buf )
01623     {
01624         switch( _var->type() )
01625         {
01626             case dods_byte_c:
01627             {
01628                 strm << DapIndent::LMarg << "_buf: " ;
01629                 strm.write( _buf, _length ) ;
01630                 strm << endl ;
01631             }
01632             break ;
01633             default:
01634             {
01635                 strm << DapIndent::LMarg << "_buf: " << (void *)_buf << endl ;
01636             }
01637             break ;
01638         }
01639     }
01640     else
01641     {
01642         strm << DapIndent::LMarg << "_buf: EMPTY" << endl ;
01643     }
01644     DapIndent::UnIndent() ;
01645 }
01646 
01647 } // namespace libdap
01648