libdap++ Updated for version 3.8.2

XDRStreamMarshaller.cc

Go to the documentation of this file.
00001 // XDRStreamMarshaller.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 
00033 #include "XDRStreamMarshaller.h"
00034 
00035 //#define DODS_DEBUG 1
00036 
00037 #include "Vector.h"
00038 #include "util.h"
00039 #include "debug.h"
00040 
00041 namespace libdap {
00042 
00043 char *XDRStreamMarshaller::_buf = 0 ;
00044 
00045 #define XDR_DAP_BUFF_SIZE 256
00046 
00047 XDRStreamMarshaller::XDRStreamMarshaller( ostream &out )
00048     : _sink( 0 ),
00049       _out( out )
00050 {
00051     if( !_buf )
00052         _buf = (char *)malloc( XDR_DAP_BUFF_SIZE ) ;
00053     if ( !_buf )
00054         throw Error("Failed to allocate memory for data serialization.");
00055 
00056     _sink = new XDR ;
00057     xdrmem_create( _sink, _buf, XDR_DAP_BUFF_SIZE, XDR_ENCODE ) ;
00058 }
00059 
00060 XDRStreamMarshaller::XDRStreamMarshaller()
00061     : Marshaller(),
00062       _sink( 0 ),
00063       _out( cout )
00064 {
00065     throw InternalErr( __FILE__, __LINE__, "Default constructor not implemented." ) ;
00066 }
00067 
00068 XDRStreamMarshaller::XDRStreamMarshaller( const XDRStreamMarshaller &m )
00069     : Marshaller( m ),
00070       _sink( 0 ),
00071       _out( cout )
00072 {
00073     throw InternalErr( __FILE__, __LINE__, "Copy constructor not implemented." ) ;
00074 }
00075 
00076 XDRStreamMarshaller &
00077 XDRStreamMarshaller::operator=( const XDRStreamMarshaller & )
00078 {
00079     throw InternalErr( __FILE__, __LINE__, "Copy operator not implemented." ) ;
00080 
00081     return *this ;
00082 }
00083 
00084 XDRStreamMarshaller::~XDRStreamMarshaller( )
00085 {
00086     if( _sink )
00087         delete_xdrstdio( _sink ) ;
00088     _sink = 0 ;
00089 }
00090 
00091 void
00092 XDRStreamMarshaller::put_byte( dods_byte val )
00093 {
00094     DBG( std::cerr << "put_byte: " << val << std::endl );
00095     if( !xdr_setpos( _sink, 0 ) )
00096         throw Error("Network I/O Error. Could not send byte data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00097 
00098     if( !xdr_char( _sink, (char *)&val ) )
00099         throw Error("Network I/O Error. Could not send byte data.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00100 
00101     unsigned int bytes_written = xdr_getpos( _sink ) ;
00102     if( !bytes_written )
00103         throw Error("Network I/O Error. Could not send byte data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00104 
00105     _out.write( _buf, bytes_written ) ;
00106 }
00107 
00108 void
00109 XDRStreamMarshaller::put_int16( dods_int16 val )
00110 {
00111     if( !xdr_setpos( _sink, 0 ) )
00112         throw Error("Network I/O Error. Could not send int 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00113 
00114     if( !XDR_INT16( _sink, &val ) )
00115         throw Error("Network I/O Error. Could not send int 16 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00116 
00117     unsigned int bytes_written = xdr_getpos( _sink ) ;
00118     if( !bytes_written )
00119         throw Error("Network I/O Error. Could not send int 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00120 
00121     _out.write( _buf, bytes_written ) ;
00122 }
00123 
00124 void
00125 XDRStreamMarshaller::put_int32( dods_int32 val )
00126 {
00127     if( !xdr_setpos( _sink, 0 ) )
00128         throw Error("Network I/O Error. Could not send int 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00129 
00130     if( !XDR_INT32( _sink, &val ) )
00131         throw Error("Network I/O Error. Culd not read int 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00132 
00133     unsigned int bytes_written = xdr_getpos( _sink ) ;
00134     if( !bytes_written )
00135         throw Error("Network I/O Error. Could not send int 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00136 
00137     _out.write( _buf, bytes_written ) ;
00138 }
00139 
00140 void
00141 XDRStreamMarshaller::put_float32( dods_float32 val )
00142 {
00143     if( !xdr_setpos( _sink, 0 ) )
00144         throw Error("Network I/O Error. Could not send float 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00145 
00146     if( !xdr_float( _sink, &val ) )
00147         throw Error("Network I/O Error. Could not send float 32 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00148 
00149     unsigned int bytes_written = xdr_getpos( _sink ) ;
00150     if( !bytes_written )
00151         throw Error("Network I/O Error. Could not send float 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00152 
00153     _out.write( _buf, bytes_written ) ;
00154 }
00155 
00156 void
00157 XDRStreamMarshaller::put_float64( dods_float64 val )
00158 {
00159     if( !xdr_setpos( _sink, 0 ) )
00160         throw Error("Network I/O Error. Could not send float 64 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00161 
00162     if( !xdr_double( _sink, &val ) )
00163         throw Error("Network I/O Error. Could not send float 64 data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00164 
00165     unsigned int bytes_written = xdr_getpos( _sink ) ;
00166     if( !bytes_written )
00167         throw Error("Network I/O Error. Could not send float 64 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00168 
00169     _out.write( _buf, bytes_written ) ;
00170 }
00171 
00172 void
00173 XDRStreamMarshaller::put_uint16( dods_uint16 val )
00174 {
00175     if( !xdr_setpos( _sink, 0 ) )
00176         throw Error("Network I/O Error. Could not send uint 16 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00177 
00178     if( !XDR_UINT16( _sink, &val ) )
00179         throw Error("Network I/O Error. Could not send uint 16 data. This may be due to a\nbug in libdap or a problem with the network connection.");
00180 
00181     unsigned int bytes_written = xdr_getpos( _sink ) ;
00182     if( !bytes_written )
00183         throw Error("Network I/O Error. Could not send uint 16 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00184 
00185     _out.write( _buf, bytes_written ) ;
00186 }
00187 
00188 void
00189 XDRStreamMarshaller::put_uint32( dods_uint32 val )
00190 {
00191     if( !xdr_setpos( _sink, 0 ) )
00192         throw Error("Network I/O Error. Could not send uint 32 data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00193 
00194     if( !XDR_UINT32( _sink, &val ) )
00195         throw Error("Network I/O Error. Could not send uint 32 data. This may be due to a\nbug in libdap or a problem with the network connection.");
00196 
00197     unsigned int bytes_written = xdr_getpos( _sink ) ;
00198     if( !bytes_written )
00199         throw Error("Network I/O Error. Could not send uint 32 data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00200 
00201     _out.write( _buf, bytes_written ) ;
00202 }
00203 
00204 void
00205 XDRStreamMarshaller::put_str( const string &val )
00206 {
00207     int size = val.length() + 8 ;
00208     char *str_buf = (char *)malloc( size ) ;
00209 
00210     if ( !str_buf ) {
00211         throw Error("Failed to allocate memory for string data serialization.");
00212     }
00213 
00214     XDR *str_sink = new XDR ;
00215     xdrmem_create( str_sink, str_buf, size, XDR_ENCODE ) ;
00216 
00217     if( !xdr_setpos( str_sink, 0 ) ) {
00218         delete_xdrstdio( str_sink ) ;
00219         free( str_buf ) ;
00220         throw Error("Network I/O Error. Could not send string data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00221     }
00222 
00223     const char *out_tmp = val.c_str() ;
00224     if( !xdr_string( str_sink, (char **)&out_tmp, size ) ) {
00225         delete_xdrstdio( str_sink ) ;
00226         free( str_buf ) ;
00227         throw Error("Network I/O Error. Could not send string data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00228     }
00229 
00230     unsigned int bytes_written = xdr_getpos( str_sink ) ;
00231     if( !bytes_written ) {
00232         delete_xdrstdio( str_sink ) ;
00233         free( str_buf ) ;
00234         throw Error("Network I/O Error. Could not send string data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00235     }
00236 
00237     _out.write( str_buf, bytes_written ) ;
00238 
00239     delete_xdrstdio( str_sink ) ;
00240     free( str_buf ) ;
00241 }
00242 
00243 void
00244 XDRStreamMarshaller::put_url( const string &val )
00245 {
00246     put_str( val ) ;
00247 }
00248 
00249 void
00250 XDRStreamMarshaller::put_opaque( char *val, unsigned int len )
00251 {
00252     if( len > XDR_DAP_BUFF_SIZE )
00253         throw Error("Network I/O Error. Could not send opaque data - length of opaque data larger than allowed");
00254 
00255     if( !xdr_setpos( _sink, 0 ) )
00256         throw Error("Network I/O Error. Could not send opaque data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00257 
00258     if( !xdr_opaque( _sink, val, len ) )
00259         throw Error("Network I/O Error. Could not send opaque data.\nThis may be due to a bug in libdap, on the server or a\nproblem with the network connection.");
00260 
00261     unsigned int bytes_written = xdr_getpos( _sink ) ;
00262     if( !bytes_written )
00263         throw Error("Network I/O Error. Could not send opaque data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00264 
00265     _out.write( _buf, bytes_written ) ;
00266 }
00267 
00268 void
00269 XDRStreamMarshaller::put_int( int val )
00270 {
00271     if( !xdr_setpos( _sink, 0 ) )
00272         throw Error("Network I/O Error. Could not send int data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00273 
00274     if( !xdr_int( _sink, &val) )
00275         throw Error("Network I/O Error(1). Could not send int data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
00276 
00277     unsigned int bytes_written = xdr_getpos( _sink ) ;
00278     if( !bytes_written )
00279         throw Error("Network I/O Error. Could not send int data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00280 
00281     _out.write( _buf, bytes_written ) ;
00282 }
00283 
00284 void
00285 XDRStreamMarshaller::put_vector( char *val, int num, Vector & )
00286 {
00287     if (!val)
00288         throw InternalErr(__FILE__, __LINE__, "Could not send byte vector data. Buffer pointer is not set.");
00289 
00290     // write the number of members of the array being written and then set the position to 0
00291     put_int( num ) ;
00292 
00293     // this is the word boundary for writing xdr bytes in a vector.
00294     unsigned int add_to = 8 ;
00295 
00296     char *byte_buf = (char *)malloc( num + add_to ) ;
00297     if ( !byte_buf ) {
00298         throw Error("Failed to allocate memory for byte vector data serialization.");
00299     }
00300 
00301     XDR *byte_sink = new XDR ;
00302     xdrmem_create( byte_sink, byte_buf, num + add_to, XDR_ENCODE ) ;
00303 
00304     if( !xdr_setpos( byte_sink, 0 ) ) {
00305         delete_xdrstdio( byte_sink ) ;
00306         free(byte_buf);
00307         throw Error("Network I/O Error. Could not send byte vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00308     }
00309 
00310     if( !xdr_bytes( byte_sink, (char **)&val, (unsigned int *) &num,
00311                     num + add_to ) )
00312     {
00313         delete_xdrstdio( byte_sink ) ;
00314         free(byte_buf);
00315         throw Error("Network I/O Error(2). Could not send byte vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
00316     }
00317 
00318     unsigned int bytes_written = xdr_getpos( byte_sink ) ;
00319     if( !bytes_written ) {
00320         delete_xdrstdio( byte_sink ) ;
00321         free(byte_buf);
00322         throw Error("Network I/O Error. Could not send byte vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00323     }
00324 
00325     _out.write( byte_buf, bytes_written ) ;
00326 
00327     delete_xdrstdio( byte_sink ) ;
00328     free( byte_buf ) ;
00329 }
00330 
00331 void
00332 XDRStreamMarshaller::put_vector( char *val, int num, int width, Vector &vec )
00333 {
00334     if (!val)
00335         throw InternalErr(__FILE__, __LINE__,
00336                           "Buffer pointer is not set.");
00337     // write the number of array members being written, then set the position back to 0
00338     put_int( num ) ;
00339 
00340     int use_width = width ;
00341     if( use_width < 4 )
00342         use_width = 4 ;
00343 
00344     // the size is the number of elements num times the width of each
00345     // element, then add 4 bytes for the number of elements
00346     int size = ( num * use_width ) + 4 ;
00347 
00348     // allocate enough memory for the elements
00349     char *vec_buf = (char *)malloc( size ) ;
00350     if ( !vec_buf ) {
00351         free(vec_buf);
00352         throw Error("Failed to allocate memory for vector data serialization.");
00353     }
00354 
00355     XDR *vec_sink = new XDR ;
00356     xdrmem_create( vec_sink, vec_buf, size, XDR_ENCODE ) ;
00357 
00358     // set the position of the sink to 0, we're starting at the beginning
00359     if( !xdr_setpos( vec_sink, 0 ) ) {
00360         delete_xdrstdio( vec_sink ) ;
00361         free(vec_buf);
00362         throw Error("Network I/O Error. Could not send vector data - unable to set stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00363     }
00364 
00365     BaseType *var = vec.var() ;
00366 
00367     // write the array to the buffer
00368     if( !xdr_array( vec_sink, (char **)&val,
00369                     (unsigned int *) & num,
00370                     size, width,
00371                     XDRUtils::xdr_coder( var->type() ) ) )
00372     {
00373         delete_xdrstdio( vec_sink ) ;
00374         free(vec_buf);
00375         throw Error("Network I/O Error(2). Could not send vector data.\nThis may be due to a bug in libdap or a\nproblem with the network connection.");
00376     }
00377 
00378     // how much was written to the buffer
00379     unsigned int bytes_written = xdr_getpos( vec_sink ) ;
00380     if( !bytes_written ) {
00381         delete_xdrstdio( vec_sink ) ;
00382         free(vec_buf);
00383         throw Error("Network I/O Error. Could not send vector data - unable to get stream position.\nThis may be due to a bug in DODS, on the server or a\nproblem with the network connection.");
00384     }
00385 
00386     // write that much out to the output stream
00387     _out.write( vec_buf, bytes_written ) ;
00388 
00389     delete_xdrstdio( vec_sink ) ;
00390     free( vec_buf ) ;
00391 }
00392 
00393 void
00394 XDRStreamMarshaller::dump(ostream &strm) const
00395 {
00396     strm << DapIndent::LMarg << "XDRStreamMarshaller::dump - ("
00397          << (void *)this << ")" << endl ;
00398 }
00399 
00400 } // namespace libdap
00401