libdap
Updated for version 3.17.0
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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::d_buf = 0; 00052 00053 XDRStreamUnMarshaller::XDRStreamUnMarshaller(istream &in) : /*&d_source( 0 ),*/ 00054 d_in(in) 00055 { 00056 if (!d_buf) 00057 d_buf = (char *) malloc(XDR_DAP_BUFF_SIZE); 00058 if (!d_buf) 00059 throw Error(internal_error, "Failed to allocate memory for data serialization."); 00060 00061 //&d_source = new XDR; 00062 xdrmem_create(&d_source, d_buf, XDR_DAP_BUFF_SIZE, XDR_DECODE); 00063 } 00064 00065 XDRStreamUnMarshaller::XDRStreamUnMarshaller() : 00066 UnMarshaller(), /*&d_source( 0 ),*/d_in(cin) 00067 { 00068 throw InternalErr(__FILE__, __LINE__, "Default constructor not implemented."); 00069 } 00070 00071 XDRStreamUnMarshaller::XDRStreamUnMarshaller(const XDRStreamUnMarshaller &um) : 00072 UnMarshaller(um), /*&d_source( 0 ),*/d_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 xdr_destroy( &d_source ); 00088 //&d_source = 0; 00089 } 00090 00091 void XDRStreamUnMarshaller::get_byte(dods_byte &val) 00092 { 00093 if (xdr_setpos( &d_source, 0 ) < 0) 00094 throw Error("Failed to reposition input stream"); 00095 if (!(d_in.read(d_buf, 4))) { 00096 if (d_in.eof()) 00097 throw Error("Premature EOF in input stream"); 00098 else { 00099 ostringstream ss("Error reading from input stream: "); 00100 ss << d_in.rdstate(); 00101 throw Error(ss.str()); 00102 } 00103 } 00104 00105 DBG2( std::cerr << "_in.gcount(): " << d_in.gcount() << std::endl ); DBG2( std::cerr << "_in.tellg(): " << d_in.tellg() << std::endl ); DBG2( std::cerr << "_buf[0]: " << hex << d_buf[0] << "; _buf[1]: " << d_buf[1] 00106 << "; _buf[2]: " << d_buf[2] << "; _buf[3]: " << d_buf[3] 00107 << dec << std::endl ); 00108 00109 if (!xdr_char(&d_source, (char *) &val)) 00110 throw Error("Network I/O Error. Could not read byte data."); 00111 00112 DBG2(std::cerr << "get_byte: " << val << std::endl ); 00113 } 00114 00115 void XDRStreamUnMarshaller::get_int16(dods_int16 &val) 00116 { 00117 xdr_setpos( &d_source, 0); 00118 d_in.read(d_buf, 4); 00119 00120 if (!XDR_INT16(&d_source, &val)) 00121 throw Error("Network I/O Error. Could not read int 16 data."); 00122 } 00123 00124 void XDRStreamUnMarshaller::get_int32(dods_int32 &val) 00125 { 00126 xdr_setpos( &d_source, 0); 00127 d_in.read(d_buf, 4); 00128 00129 if (!XDR_INT32(&d_source, &val)) 00130 throw Error("Network I/O Error. Could not read int 32 data."); 00131 } 00132 00133 void XDRStreamUnMarshaller::get_float32(dods_float32 &val) 00134 { 00135 xdr_setpos( &d_source, 0); 00136 d_in.read(d_buf, 4); 00137 00138 if (!xdr_float(&d_source, &val)) 00139 throw Error("Network I/O Error. Could not read float 32 data."); 00140 } 00141 00142 void XDRStreamUnMarshaller::get_float64(dods_float64 &val) 00143 { 00144 xdr_setpos( &d_source, 0); 00145 d_in.read(d_buf, 8); 00146 00147 if (!xdr_double(&d_source, &val)) 00148 throw Error("Network I/O Error. Could not read float 64 data."); 00149 } 00150 00151 void XDRStreamUnMarshaller::get_uint16(dods_uint16 &val) 00152 { 00153 xdr_setpos( &d_source, 0); 00154 d_in.read(d_buf, 4); 00155 00156 if (!XDR_UINT16(&d_source, &val)) 00157 throw Error("Network I/O Error. Could not read uint 16 data."); 00158 } 00159 00160 void XDRStreamUnMarshaller::get_uint32(dods_uint32 &val) 00161 { 00162 xdr_setpos( &d_source, 0); 00163 d_in.read(d_buf, 4); 00164 00165 if (!XDR_UINT32(&d_source, &val)) 00166 throw Error("Network I/O Error. Could not read uint 32 data."); 00167 } 00168 00169 void XDRStreamUnMarshaller::get_str(string &val) 00170 { 00171 int i; 00172 get_int(i); 00173 DBG(std::cerr << "i: " << i << std::endl); 00174 00175 // Must round up string size to next 4 00176 i = ((i + 3) / 4) * 4; 00177 DBG(std::cerr << "i: " << i << std::endl); 00178 00179 char *in_tmp = 0; 00180 //char *buf = 0; 00181 //XDR *source = 0; 00182 // Must address the case where the string is larger than the buffer 00183 if (i + 4 > XDR_DAP_BUFF_SIZE) { 00184 #if 0 00185 char *buf = (char *) malloc(i + 4); 00186 if (!buf) 00187 throw InternalErr(__FILE__, __LINE__, "Error allocating memory"); 00188 #endif 00189 vector<char> buf(i+4); 00190 00191 XDR source;// = new XDR; 00192 xdrmem_create(&source, &buf[0], i + 4, XDR_DECODE); 00193 memcpy(&buf[0], d_buf, 4); 00194 00195 d_in.read(&buf[0] + 4, i); 00196 00197 xdr_setpos( &source, 0); 00198 if (!xdr_string( &source, &in_tmp, max_str_len)) { 00199 xdr_destroy( &source ); 00200 throw Error("Network I/O Error. Could not read string data."); 00201 } 00202 00203 xdr_destroy( &source ); 00204 } 00205 else { 00206 d_in.read(d_buf + 4, i); 00207 00208 xdr_setpos( &d_source, 0); 00209 if (!xdr_string(&d_source, &in_tmp, max_str_len)) 00210 throw Error("Network I/O Error. Could not read string data."); 00211 } 00212 00213 val = in_tmp; 00214 00215 free(in_tmp); 00216 } 00217 00218 void XDRStreamUnMarshaller::get_url(string &val) 00219 { 00220 get_str(val); 00221 } 00222 00223 void XDRStreamUnMarshaller::get_opaque(char *val, unsigned int len) 00224 { 00225 xdr_setpos( &d_source, 0); 00226 00227 // Round len up to the next multiple of 4. There is also the RNDUP() 00228 // macro in xdr.h, at least on OS/X. 00229 len += len & 3; 00230 if (static_cast<int>(len) > XDR_DAP_BUFF_SIZE) 00231 throw Error("Network I/O Error. Length of opaque data larger than allowed"); 00232 00233 d_in.read(d_buf, len); 00234 00235 xdr_opaque(&d_source, val, len); 00236 } 00237 00238 void XDRStreamUnMarshaller::get_int(int &val) 00239 { 00240 xdr_setpos( &d_source, 0); 00241 d_in.read(d_buf, 4); 00242 00243 if (!xdr_int(&d_source, &val)) 00244 throw Error("Network I/O Error(1)."); 00245 00246 DBG(std::cerr << "get_int: " << val << std::endl); 00247 } 00248 00249 void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, Vector &) 00250 { 00251 int i; 00252 get_int(i); // This leaves the XDR encoded value in d_buf; used later 00253 DBG(std::cerr << "i: " << i << std::endl); 00254 00255 // Must round up string size to next 4 00256 i += i & 3; 00257 DBG(std::cerr << "i: " << i << std::endl); 00258 00259 //char *buf = 0; 00260 //XDR *source = 0; 00261 // Must address the case where the string is larger than the buffer 00262 if (i + 4 > XDR_DAP_BUFF_SIZE) { 00263 vector<char> buf(i+4); 00264 XDR source; 00265 xdrmem_create(&source, &buf[0], i + 4, XDR_DECODE); 00266 memcpy(&buf[0], d_buf, 4); 00267 00268 d_in.read(&buf[0] + 4, i); 00269 DBG2(cerr << "bytes read: " << d_in.gcount() << endl); 00270 00271 xdr_setpos(&source, 0); 00272 if (!xdr_bytes(&d_source, val, &num, DODS_MAX_ARRAY)) { 00273 xdr_destroy(&source); 00274 throw Error("Network I/O Error. Could not read byte array data."); 00275 } 00276 00277 xdr_destroy( &source ); 00278 } 00279 else { 00280 d_in.read(d_buf + 4, i); 00281 DBG2(cerr << "bytes read: " << d_in.gcount() << endl); 00282 00283 xdr_setpos(&d_source, 0); 00284 if (!xdr_bytes(&d_source, val, &num, DODS_MAX_ARRAY)) 00285 throw Error("Network I/O Error. Could not read byte array data."); 00286 } 00287 } 00288 00289 void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, int width, Vector &vec) 00290 { 00291 get_vector(val, num, width, vec.var()->type()); 00292 } 00293 00294 void XDRStreamUnMarshaller::get_vector(char **val, unsigned int &num, int width, Type type) 00295 { 00296 int i; 00297 get_int(i); // This leaves the XDR encoded value in d_buf; used later 00298 DBG(std::cerr << "i: " << i << std::endl); 00299 00300 width += width & 3; 00301 DBG(std::cerr << "width: " << width << std::endl); 00302 00303 int size = i * width; // + 4; // '+ 4' to hold the int already read 00304 00305 // Must address the case where the string is larger than the buffer 00306 if (size > XDR_DAP_BUFF_SIZE) { 00307 vector<char> buf(size+4); 00308 XDR source; 00309 xdrmem_create(&source, &buf[0], size + 4, XDR_DECODE); 00310 DBG(cerr << "size: " << size << endl); 00311 memcpy(&buf[0], d_buf, 4); 00312 00313 d_in.read(&buf[0] + 4, size); // +4 for the int already read 00314 DBG(cerr << "bytes read: " << d_in.gcount() << endl); 00315 00316 xdr_setpos(&source, 0); 00317 if (!xdr_array(&source, val, &num, DODS_MAX_ARRAY, width, XDRUtils::xdr_coder(type))) { 00318 xdr_destroy( &source ); 00319 throw Error("Network I/O Error. Could not read array data."); 00320 } 00321 00322 xdr_destroy( &source ); 00323 } 00324 else { 00325 d_in.read(d_buf + 4, size); 00326 DBG(cerr << "bytes read (2): " << d_in.gcount() << endl); 00327 00328 xdr_setpos( &d_source, 0); 00329 if (!xdr_array(&d_source, val, &num, DODS_MAX_ARRAY, width, XDRUtils::xdr_coder(type))) 00330 throw Error("Network I/O Error. Could not read array data."); 00331 } 00332 } 00333 00334 void XDRStreamUnMarshaller::dump(ostream &strm) const 00335 { 00336 strm << DapIndent::LMarg << "XDRStreamUnMarshaller::dump - (" << (void *) this << ")" << endl; 00337 } 00338 00339 } // namespace libdap 00340