libdap++ Updated for version 3.8.2
|
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