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         source = new XDR;
00196         buf = (char *) malloc( i + 4 );
00197         xdrmem_create(source, buf, i + 4, XDR_DECODE);
00198         memcpy( buf, _buf, 4 );
00199 
00200         _in.read( buf + 4, i );
00201 
00202         xdr_setpos( source, 0 );
00203         if( !xdr_string( source, &in_tmp, max_str_len ) )
00204             throw Error("Network I/O Error. Could not read string data.");
00205 
00206         delete_xdrstdio( source );
00207     }
00208     else {
00209         _in.read( _buf + 4, i );
00210 
00211         xdr_setpos( _source, 0 );
00212         if( !xdr_string( _source, &in_tmp, max_str_len ) )
00213             throw Error("Network I/O Error. Could not read string data.");
00214     }
00215 
00216     val = in_tmp ;
00217 
00218     free( in_tmp ) ;
00219 }
00220 
00221 void
00222 XDRStreamUnMarshaller::get_url( string &val )
00223 {
00224     get_str( val ) ;
00225 }
00226 
00227 void
00228 XDRStreamUnMarshaller::get_opaque( char *val, unsigned int len )
00229 {
00230     xdr_setpos( _source, 0 );
00231 
00232     // Round len up to the next multiple of 4. There is also the RNDUP()
00233     // macro in xdr.h, at least on OS/X.
00234     len += len&3;
00235     if ( static_cast<int>(len) > XDR_DAP_BUFF_SIZE )
00236         throw Error("Network I/O Error. Length of opaque data larger than allowed");
00237 
00238     _in.read( _buf, len );
00239 
00240      xdr_opaque( _source, val, len ) ;
00241 }
00242 
00243 void
00244 XDRStreamUnMarshaller::get_int( int &val )
00245 {
00246     xdr_setpos( _source, 0 );
00247     _in.read( _buf, 4 );
00248 
00249     if( !xdr_int( _source, &val ) )
00250         throw Error("Network I/O Error(1).");
00251 
00252     DBG(std::cerr << "get_int: " << val << std::endl);
00253 }
00254 
00255 void
00256 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, Vector & )
00257 {
00258     int i;
00259     get_int( i ) ;  // This leaves the XDR encoded value in _buf; used later
00260     DBG(std::cerr << "i: " << i << std::endl);
00261 
00262     // Must round up string size to next 4
00263     i += i&3;
00264     DBG(std::cerr << "i: " << i << std::endl);
00265 
00266     char *buf = 0;
00267     XDR *source = 0;
00268     // Must address the case where the string is larger than the buffer
00269     if ( i + 4 > XDR_DAP_BUFF_SIZE ) {
00270         source = new XDR;
00271         buf = (char *) malloc( i + 4 );
00272         xdrmem_create(source, buf, i + 4, XDR_DECODE);
00273         memcpy( buf, _buf, 4 );
00274 
00275         _in.read( buf + 4, i );
00276         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00277 
00278         xdr_setpos( source, 0 );
00279         if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
00280             throw Error("Network I/O Error. Could not read byte array data.");
00281 
00282         delete_xdrstdio( source );
00283     }
00284     else {
00285         _in.read( _buf + 4, i );
00286         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00287 
00288         xdr_setpos( _source, 0 );
00289         if( !xdr_bytes( _source, val, &num, DODS_MAX_ARRAY) )
00290             throw Error("Network I/O Error. Could not read byte array data.");
00291     }
00292 }
00293 
00294 void
00295 XDRStreamUnMarshaller::get_vector( char **val, unsigned int &num, int width, Vector &vec )
00296 {
00297     int i;
00298     get_int( i ) ; // This leaves the XDR encoded value in _buf; used later
00299     DBG(std::cerr << "i: " << i << std::endl);
00300 
00301     width += width&3;
00302     DBG(std::cerr << "width: " << width << std::endl);
00303 
00304     char *buf = 0;
00305     XDR *source = 0;
00306     int size = i * width; // + 4; // '+ 4' to hold the int already read
00307     BaseType *var = vec.var();
00308 
00309     // Must address the case where the string is larger than the buffer
00310     if (size > XDR_DAP_BUFF_SIZE) {
00311         source = new XDR;
00312         buf = (char *) malloc( size + 4 );
00313         xdrmem_create(source, buf, size + 4, XDR_DECODE);
00314         DBG2(cerr << "size: " << size << endl);
00315         memcpy(buf, _buf, 4);
00316 
00317         _in.read(buf + 4, size); // +4 for the int already read
00318         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00319 
00320         xdr_setpos( source, 0 );
00321         if (!xdr_array( source, val, &num, DODS_MAX_ARRAY, width,
00322                         XDRUtils::xdr_coder( var->type() ) ) )
00323             throw Error("Network I/O Error. Could not read array data.");
00324 
00325         delete_xdrstdio(source);
00326     }
00327     else {
00328         _in.read(_buf + 4, size);
00329         DBG2(cerr << "bytes read: " << _in.gcount() << endl);
00330 
00331         xdr_setpos( _source, 0 );
00332         if (!xdr_array( _source, val, &num, DODS_MAX_ARRAY, width,
00333                         XDRUtils::xdr_coder( var->type() ) ) )
00334             throw Error("Network I/O Error. Could not read array data.");
00335     }
00336 }
00337 
00338 void
00339 XDRStreamUnMarshaller::dump(ostream &strm) const
00340 {
00341     strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - ("
00342          << (void *)this << ")" << endl ;
00343 }
00344 
00345 } // namespace libdap
00346