libdap++  Updated for version 3.8.2
XDRStreamUnMarshaller.cc
Go to the documentation of this file.
00001 // XDRStreamUnMarshaller.cc
00002 
00003 // -*- mode: c++; c-basic-offset:4 -*-
00004 
00005 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00006 // Access Protocol.
00007 
00008 // Copyright (c) 2002,2003 OPeNDAP, Inc.
00009 // Author: Patrick West <pwest@ucar.edu>
00010 //
00011 // This library is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU Lesser General Public
00013 // License as published by the Free Software Foundation; either
00014 // version 2.1 of the License, or (at your option) any later version.
00015 //
00016 // This library is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 //
00025 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00026 
00027 // (c) COPYRIGHT URI/MIT 1994-1999
00028 // Please read the full copyright statement in the file COPYRIGHT_URI.
00029 //
00030 // Authors:
00031 //      pwest       Patrick West <pwest@ucar.edu>
00032 #include "config.h"
00033 #include "XDRStreamUnMarshaller.h"
00034 
00035 #include <cstring> // for memcpy
00036 #include <string>
00037 #include <sstream>
00038 
00039 #define DODS_DEBUG2 1
00040 #define DODS_DEBUG 1
00041 
00042 #include "Str.h"
00043 #include "Vector.h"
00044 #include "Array.h"
00045 #include "util.h"
00046 #include "InternalErr.h"
00047 #include "debug.h"
00048 
00049 namespace libdap {
00050 
00051 char *XDRStreamUnMarshaller::_buf = 0 ;
00052 
00053 XDRStreamUnMarshaller::XDRStreamUnMarshaller( istream &in )
00054     : _source( 0 ), _in( in )
00055 {
00056     if (!_buf)
00057         _buf = (char *) malloc(XDR_DAP_BUFF_SIZE);
00058     if (!_buf)
00059         throw Error("Failed to allocate memory for data serialization.");
00060 
00061     _source = new XDR;
00062     xdrmem_create(_source, _buf, XDR_DAP_BUFF_SIZE, XDR_DECODE);
00063 }
00064 
00065 XDRStreamUnMarshaller::XDRStreamUnMarshaller()
00066     : UnMarshaller(), _source( 0 ), _in( cin )
00067 {
00068     throw InternalErr( __FILE__, __LINE__, "Default constructor not implemented." ) ;
00069 }
00070 
00071 XDRStreamUnMarshaller::XDRStreamUnMarshaller( const XDRStreamUnMarshaller &um )
00072     : UnMarshaller( um ), _source( 0 ), _in( cin )
00073 {
00074     throw InternalErr( __FILE__, __LINE__, "Copy constructor not implemented." ) ;
00075 }
00076 
00077 XDRStreamUnMarshaller &
00078 XDRStreamUnMarshaller::operator=( const XDRStreamUnMarshaller & )
00079 {
00080     throw InternalErr( __FILE__, __LINE__, "Copy operator not implemented." ) ;
00081 
00082     return *this ;
00083 }
00084 
00085 XDRStreamUnMarshaller::~XDRStreamUnMarshaller( )
00086 {
00087     if ( _source )
00088         delete_xdrstdio( _source ) ;
00089     _source = 0;
00090 }
00091 
00092 void
00093 XDRStreamUnMarshaller::get_byte( dods_byte &val )
00094 {
00095     if (xdr_setpos( _source, 0 ) < 0)
00096         throw Error("Failed to reposition input stream");
00097     if (!(_in.read( _buf, 4 ))) {
00098         if (_in.eof())
00099             throw Error("Premature EOF in input stream");
00100         else {
00101             ostringstream ss("Error reading from input stream: ");
00102             ss << _in.rdstate();
00103             throw Error(ss.str());
00104         }
00105     }
00106 
00107     DBG2( std::cerr << "_in.gcount(): " << _in.gcount() << std::endl );
00108     DBG2( std::cerr << "_in.tellg(): " << _in.tellg() << std::endl );
00109     DBG2( std::cerr << "_buf[0]: " << hex << _buf[0] << "; _buf[1]: " << _buf[1]
00110              << "; _buf[2]: " << _buf[2] << "; _buf[3]: " << _buf[3]
00111              << dec << std::endl );
00112 
00113     if( !xdr_char( _source, (char *)&val ) )
00114         throw Error("Network I/O Error. Could not read byte data.");
00115 
00116     DBG2(std::cerr << "get_byte: " << val << std::endl );
00117 }
00118 
00119 void
00120 XDRStreamUnMarshaller::get_int16( dods_int16 &val )
00121 {
00122     xdr_setpos( _source, 0 );
00123     _in.read( _buf, 4 );
00124 
00125     if( !XDR_INT16( _source, &val ) )
00126         throw Error("Network I/O Error. Could not read int 16 data.");
00127 }
00128 
00129 void
00130 XDRStreamUnMarshaller::get_int32( dods_int32 &val )
00131 {
00132     xdr_setpos( _source, 0 );
00133     _in.read( _buf, 4 );
00134 
00135     if( !XDR_INT32( _source, &val ) )
00136         throw Error("Network I/O Error. Could not read int 32 data.");
00137 }
00138 
00139 void
00140 XDRStreamUnMarshaller::get_float32( dods_float32 &val )
00141 {
00142     xdr_setpos( _source, 0 );
00143     _in.read( _buf, 4 );
00144 
00145     if( !xdr_float( _source, &val ) )
00146         throw Error("Network I/O Error. Could not read float 32 data.");
00147 }
00148 
00149 void
00150 XDRStreamUnMarshaller::get_float64( dods_float64 &val )
00151 {
00152     xdr_setpos( _source, 0 );
00153     _in.read( _buf, 8 );
00154 
00155     if( !xdr_double( _source, &val ) )
00156         throw Error("Network I/O Error. Could not read float 64 data.");
00157 }
00158 
00159 void
00160 XDRStreamUnMarshaller::get_uint16( dods_uint16 &val )
00161 {
00162     xdr_setpos( _source, 0 );
00163     _in.read( _buf, 4 );
00164 
00165     if( !XDR_UINT16( _source, &val ) )
00166         throw Error("Network I/O Error. Could not read uint 16 data.");
00167 }
00168 
00169 void
00170 XDRStreamUnMarshaller::get_uint32( dods_uint32 &val )
00171 {
00172     xdr_setpos( _source, 0 );
00173     _in.read( _buf, 4 );
00174 
00175     if( !XDR_UINT32( _source, &val ) )
00176         throw Error("Network I/O Error. Could not read uint 32 data.");
00177 }
00178 
00179 void
00180 XDRStreamUnMarshaller::get_str( string &val )
00181 {
00182     int i;
00183     get_int( i ) ;
00184     DBG(std::cerr << "i: " << i << std::endl);
00185 
00186     // Must round up string size to next 4
00187     i = ( ( i + 3 ) / 4 ) * 4;
00188     DBG(std::cerr << "i: " << i << std::endl);
00189 
00190     char *in_tmp = 0;
00191     //char *buf = 0;
00192     //XDR *source = 0;
00193     // Must address the case where the string is larger than the buffer
00194     if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
00195         char *buf = (char *) malloc( i + 4 );
00196         if (!buf)
00197                 throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
00198         XDR *source = new XDR;  
00199         xdrmem_create(source, buf, i + 4, XDR_DECODE);
00200         memcpy( buf, _buf, 4 );
00201 
00202         _in.read( buf + 4, i );
00203 
00204         xdr_setpos( source, 0 );
00205         if( !xdr_string( source, &in_tmp, max_str_len ) ) {
00206             delete_xdrstdio( source );
00207             throw Error("Network I/O Error. Could not read string data.");
00208         }
00209 
00210         delete_xdrstdio( source );
00211     }
00212     else {
00213         _in.read( _buf + 4, i );
00214 
00215         xdr_setpos( _source, 0 );
00216         if( !xdr_string( _source, &in_tmp, max_str_len ) )
00217             throw Error("Network I/O Error. Could not read string data.");
00218     }
00219 
00220     val = in_tmp ;
00221 
00222     free( in_tmp ) ;
00223 }
00224 
00225 void
00226 XDRStreamUnMarshaller::get_url( string &val )
00227 {
00228     get_str( val ) ;
00229 }
00230 
00231 void
00232 XDRStreamUnMarshaller::get_opaque( char *val, unsigned int len )
00233 {
00234     xdr_setpos( _source, 0 );
00235 
00236     // Round len up to the next multiple of 4. There is also the RNDUP()
00237     // macro in xdr.h, at least on OS/X.
00238     len += len&3;
00239     if ( static_cast<int>(len) > XDR_DAP_BUFF_SIZE )
00240         throw Error("Network I/O Error. Length of opaque data larger than allowed");
00241 
00242     _in.read( _buf, len );
00243 
00244      xdr_opaque( _source, val, len ) ;
00245 }
00246 
00247 void
00248 XDRStreamUnMarshaller::get_int( int &val )
00249 {
00250     xdr_setpos( _source, 0 );
00251     _in.read( _buf, 4 );
00252 
00253     if( !xdr_int( _source, &val ) )
00254         throw Error("Network I/O Error(1).");
00255 
00256     DBG(std::cerr << "get_int: " << val << std::endl);
00257 }
00258 
00259 void
00260 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, Vector & )
00261 {
00262     int i;
00263     get_int( i ) ;  // This leaves the XDR encoded value in _buf; used later
00264     DBG(std::cerr << "i: " << i << std::endl);
00265 
00266     // Must round up string size to next 4
00267     i += i&3;
00268     DBG(std::cerr << "i: " << i << std::endl);
00269 
00270     //char *buf = 0;
00271     //XDR *source = 0;
00272     // Must address the case where the string is larger than the buffer
00273     if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
00274         char *buf = (char *) malloc( i + 4 );
00275         if (!buf)
00276                 throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
00277         XDR *source = new XDR;  
00278         xdrmem_create(source, buf, i + 4, XDR_DECODE);
00279         memcpy( buf, _buf, 4 );
00280 
00281         _in.read( buf + 4, i );
00282         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00283 
00284         xdr_setpos( source, 0 );
00285         if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) ) {
00286             delete_xdrstdio( source );
00287             throw Error("Network I/O Error. Could not read byte array data.");
00288         }
00289 
00290         delete_xdrstdio( source );
00291     }
00292     else {
00293         _in.read( _buf + 4, i );
00294         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00295 
00296         xdr_setpos( _source, 0 );
00297         if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
00298             throw Error("Network I/O Error. Could not read byte array data.");
00299     }
00300 }
00301 
00302 void
00303 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, int width, Vector &vec )
00304 {
00305     int i;
00306     get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
00307     DBG(std::cerr << "i: " << i << std::endl);
00308 
00309     width += width&3;
00310     DBG(std::cerr << "width: " << width << std::endl);
00311 
00312     //char *buf = 0;
00313     //XDR *source = 0;
00314     int size = i * width; // + 4; // '+ 4' to hold the int already read
00315     BaseType *var = vec.var();
00316 
00317     // Must address the case where the string is larger than the buffer
00318     if (size > XDR_DAP_BUFF_SIZE) {
00319         char *buf = (char *) malloc( size + 4 );
00320         if (!buf)
00321                 throw InternalErr(__FILE__, __LINE__, "Error allocating memory");
00322         XDR *source = new XDR;  
00323         xdrmem_create(source, buf, size + 4, XDR_DECODE);
00324         DBG2(cerr << "size: " << size << endl);
00325         memcpy(buf, _buf, 4);
00326 
00327         _in.read(buf + 4, size); // +4 for the int already read
00328         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00329 
00330         xdr_setpos( source, 0 );
00331         if (!xdr_array( source, val, &num, DODS_MAX_ARRAY, width,
00332                         XDRUtils::xdr_coder( var->type() ) ) ) {
00333             delete_xdrstdio( source );
00334             throw Error("Network I/O Error. Could not read array data.");
00335         }
00336 
00337         delete_xdrstdio(source);
00338     }
00339     else {
00340         _in.read(_buf + 4, size);
00341         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00342 
00343         xdr_setpos( _source, 0 );
00344         if (!xdr_array( _source, val, &num, DODS_MAX_ARRAY, width,
00345                         XDRUtils::xdr_coder( var->type() ) ) )
00346             throw Error("Network I/O Error. Could not read array data.");
00347     }
00348 }
00349 
00350 void
00351 XDRStreamUnMarshaller::dump(ostream &strm) const
00352 {
00353     strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - ("
00354          << (void *)this << ")" << endl ;
00355 }
00356 
00357 } // namespace libdap
00358