libdap
Updated for version 3.17.0
|
00001 // D4StreamUnMarshaller.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) 2012 OPeNDAP, Inc. 00009 // Author: James Gallagher <jgallagher@opendap.org> 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 #include "config.h" 00028 00029 #include <byteswap.h> 00030 #include <cassert> 00031 00032 #include <iostream> 00033 #include <iomanip> 00034 #include <limits> 00035 #include <string> 00036 #include <sstream> 00037 00038 //#define DODS_DEBUG2 1 00039 //#define DODS_DEBUG 1 00040 00041 #include "util.h" 00042 //#include "XDRUtils.h" 00043 #include "InternalErr.h" 00044 #include "D4StreamUnMarshaller.h" 00045 #include "debug.h" 00046 00047 namespace libdap { 00048 00059 D4StreamUnMarshaller::D4StreamUnMarshaller(istream &in, bool twiddle_bytes) : d_in( in ), d_twiddle_bytes(twiddle_bytes) 00060 { 00061 assert(sizeof(std::streamsize) >= sizeof(int64_t)); 00062 00063 #if USE_XDR_FOR_IEEE754_ENCODING 00064 // XDR is used to handle transforming non-ieee754 reals, nothing else. 00065 xdrmem_create(&d_source, d_buf, sizeof(dods_float64), XDR_DECODE); 00066 #endif 00067 00068 // This will cause exceptions to be thrown on i/o errors. The exception 00069 // will be ostream::failure 00070 d_in.exceptions(istream::failbit | istream::badbit); 00071 00072 } 00073 00080 D4StreamUnMarshaller::D4StreamUnMarshaller(istream &in) : d_in( in ), d_twiddle_bytes(false) 00081 { 00082 assert(sizeof(std::streamsize) >= sizeof(int64_t)); 00083 00084 #if USE_XDR_FOR_IEEE754_ENCODING 00085 // XDR is used to handle transforming non-ieee754 reals, nothing else. 00086 xdrmem_create(&d_source, d_buf, sizeof(dods_float64), XDR_DECODE); 00087 #endif 00088 00089 // This will cause exceptions to be thrown on i/o errors. The exception 00090 // will be ostream::failure 00091 d_in.exceptions(istream::failbit | istream::badbit); 00092 } 00093 00094 D4StreamUnMarshaller::~D4StreamUnMarshaller( ) 00095 { 00096 #if USE_XDR_FOR_IEEE754_ENCODING 00097 xdr_destroy(&d_source); 00098 #endif 00099 } 00100 00101 Crc32::checksum D4StreamUnMarshaller::get_checksum() 00102 { 00103 Crc32::checksum c; 00104 d_in.read(reinterpret_cast<char*>(&c), sizeof(Crc32::checksum)); 00105 00106 return c; 00107 } 00108 00109 string D4StreamUnMarshaller::get_checksum_str() 00110 { 00111 ostringstream oss; 00112 oss.setf(ios::hex, ios::basefield); 00113 oss << setfill('0') << setw(8) << get_checksum(); 00114 00115 return oss.str(); 00116 } 00117 00118 void 00119 D4StreamUnMarshaller::get_byte( dods_byte &val ) 00120 { 00121 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_byte)); 00122 } 00123 00124 void 00125 D4StreamUnMarshaller::get_int8( dods_int8 &val ) 00126 { 00127 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_int8)); 00128 } 00129 00130 void 00131 D4StreamUnMarshaller::get_int16( dods_int16 &val ) 00132 { 00133 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_int16)); 00134 if (d_twiddle_bytes) 00135 val = bswap_16(val); 00136 } 00137 00138 void 00139 D4StreamUnMarshaller::get_int32( dods_int32 &val ) 00140 { 00141 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_int32)); 00142 if (d_twiddle_bytes) 00143 val = bswap_32(val); 00144 } 00145 00146 void 00147 D4StreamUnMarshaller::get_int64( dods_int64 &val ) 00148 { 00149 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_int64)); 00150 if (d_twiddle_bytes) 00151 val = bswap_64(val); 00152 } 00153 00154 void 00155 D4StreamUnMarshaller::get_float32( dods_float32 &val ) 00156 { 00157 #if !USE_XDR_FOR_IEEE754_ENCODING 00158 assert(std::numeric_limits<float>::is_iec559); 00159 00160 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_float32)); 00161 if (d_twiddle_bytes) { 00162 dods_int32 *i = reinterpret_cast<dods_int32*>(&val); 00163 *i = bswap_32(*i); 00164 } 00165 00166 #else 00167 if (std::numeric_limits<float>::is_iec559) { 00168 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_float32)); 00169 if (d_twiddle_bytes) { 00170 dods_int32 *i = reinterpret_cast<dods_int32*>(&val); 00171 *i = bswap_32(*i); 00172 } 00173 00174 } 00175 else { 00176 xdr_setpos( &d_source, 0); 00177 d_in.read(d_buf, sizeof(dods_float32)); 00178 00179 if (!xdr_float(&d_source, &val)) 00180 throw Error("Network I/O Error. Could not read float 64 data."); 00181 } 00182 #endif 00183 } 00184 00185 void 00186 D4StreamUnMarshaller::get_float64( dods_float64 &val ) 00187 { 00188 #if !USE_XDR_FOR_IEEE754_ENCODING 00189 assert(std::numeric_limits<double>::is_iec559); 00190 00191 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_float64)); 00192 if (d_twiddle_bytes) { 00193 dods_int64 *i = reinterpret_cast<dods_int64*>(&val); 00194 *i = bswap_64(*i); 00195 } 00196 00197 #else 00198 if (std::numeric_limits<float>::is_iec559) { 00199 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_float64)); 00200 if (d_twiddle_bytes) { 00201 dods_int64 *i = reinterpret_cast<dods_int64*>(&val); 00202 *i = bswap_64(*i); 00203 } 00204 } 00205 else { 00206 xdr_setpos( &d_source, 0); 00207 d_in.read(d_buf, sizeof(dods_float64)); 00208 00209 if (!xdr_double(&d_source, &val)) 00210 throw Error("Network I/O Error. Could not read float 64 data."); 00211 } 00212 #endif 00213 } 00214 00215 void 00216 D4StreamUnMarshaller::get_uint16( dods_uint16 &val ) 00217 { 00218 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_uint16)); 00219 if (d_twiddle_bytes) 00220 val = bswap_16(val); 00221 } 00222 00223 void 00224 D4StreamUnMarshaller::get_uint32( dods_uint32 &val ) 00225 { 00226 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_uint32)); 00227 if (d_twiddle_bytes) 00228 val = bswap_32(val); 00229 } 00230 00231 void 00232 D4StreamUnMarshaller::get_uint64( dods_uint64 &val ) 00233 { 00234 d_in.read(reinterpret_cast<char*>(&val), sizeof(dods_uint64)); 00235 if (d_twiddle_bytes) 00236 val = bswap_64(val); 00237 } 00238 00239 void 00240 D4StreamUnMarshaller::get_str( string &val ) 00241 { 00242 int64_t len; 00243 d_in.read(reinterpret_cast<char*>(&len), sizeof(int64_t)); 00244 00245 val.resize(len); 00246 d_in.read(&val[0], len); 00247 } 00248 00249 void 00250 D4StreamUnMarshaller::get_url( string &val ) 00251 { 00252 get_str( val ) ; 00253 } 00254 00263 int64_t 00264 D4StreamUnMarshaller::get_count() 00265 { 00266 int64_t count; 00267 d_in.read(reinterpret_cast<char*>(&count), sizeof(count)); 00268 return count; 00269 } 00270 00278 void 00279 D4StreamUnMarshaller::get_opaque_dap4( char **val, int64_t &len ) 00280 { 00281 //len = get_length_prefix(); 00282 d_in.read(reinterpret_cast<char*>(&len), sizeof(len)); 00283 00284 *val = new char[len]; 00285 d_in.read(*val, len); 00286 } 00287 00288 void 00289 D4StreamUnMarshaller::get_opaque_dap4( vector<uint8_t> &val ) 00290 { 00291 //len = get_length_prefix(); 00292 int64_t len; 00293 d_in.read(reinterpret_cast<char*>(&len), sizeof(len)); 00294 00295 val.resize(len); 00296 d_in.read(reinterpret_cast<char*>(&val[0]), len); 00297 } 00298 00299 void 00300 D4StreamUnMarshaller::get_vector( char *val, int64_t bytes ) 00301 { 00302 d_in.read(val, bytes); 00303 } 00304 00305 #if USE_XDR_FOR_IEEE754_ENCODING 00306 void D4StreamUnMarshaller::m_deserialize_reals(char *val, int64_t num, int width, Type type) 00307 { 00308 int64_t size = num * width; 00309 // char *buf = (char*)malloc(size); jhrg 7/23/13 00310 vector<char> buf(size); 00311 XDR xdr; 00312 xdrmem_create(&xdr, &buf[0], size, XDR_DECODE); 00313 try { 00314 xdr_setpos(&d_source, 0); 00315 d_in.read(&buf[0], size); 00316 00317 if(!xdr_array(&xdr, &val, (unsigned int *)&num, size, width, XDRUtils::xdr_coder(type))) 00318 throw InternalErr(__FILE__, __LINE__, "Error deserializing a Float64 array"); 00319 00320 if (xdr_getpos(&xdr) != size) 00321 throw InternalErr(__FILE__, __LINE__, "Error deserializing a Float64 array"); 00322 } 00323 catch (...) { 00324 xdr_destroy(&xdr); 00325 throw; 00326 } 00327 xdr_destroy(&xdr); 00328 } 00329 #endif 00330 00331 void D4StreamUnMarshaller::m_twidle_vector_elements(char *vals, int64_t num, int width) 00332 { 00333 switch (width) { 00334 case 2: { 00335 dods_int16 *local = reinterpret_cast<dods_int16*>(vals); 00336 while (num--) { 00337 *local = bswap_16(*local); 00338 local++; 00339 } 00340 break; 00341 } 00342 case 4: { 00343 dods_int32 *local = reinterpret_cast<dods_int32*>(vals);; 00344 while (num--) { 00345 *local = bswap_32(*local); 00346 local++; 00347 } 00348 break; 00349 } 00350 case 8: { 00351 dods_int64 *local = reinterpret_cast<dods_int64*>(vals);; 00352 while (num--) { 00353 *local = bswap_64(*local); 00354 local++; 00355 } 00356 break; 00357 } 00358 default: 00359 throw InternalErr(__FILE__, __LINE__, "Unrecognized word size."); 00360 } 00361 } 00362 00363 void 00364 D4StreamUnMarshaller::get_vector(char *val, int64_t num_elem, int elem_size) 00365 { 00366 assert(std::numeric_limits<float>::is_iec559); 00367 assert(std::numeric_limits<double>::is_iec559); 00368 assert(val); 00369 assert(num_elem >= 0); 00370 assert(elem_size > 0); 00371 00372 int64_t bytes; 00373 00374 switch (elem_size) { 00375 case 1: 00376 assert(!"Don't call this method for bytes, use put_vector(val, bytes) instead"); 00377 bytes = num_elem; 00378 break; 00379 case 2: 00380 // Don't bother testing the sign bit 00381 assert(!(num_elem & 0x4000000000000000)); // 0x 40 00 --> 0100 0000 00382 bytes = num_elem << 1; 00383 break; 00384 case 4: 00385 assert(!(num_elem & 0x6000000000000000)); // 0x 60 00 --> 0110 0000 00386 bytes = num_elem << 2; 00387 break; 00388 case 8: 00389 assert(!(num_elem & 0x7000000000000000)); // 0111 0000 00390 bytes = num_elem << 3; 00391 break; 00392 default: 00393 bytes = num_elem * elem_size; 00394 break; 00395 } 00396 00397 d_in.read(val, bytes); 00398 00399 if (d_twiddle_bytes) 00400 m_twidle_vector_elements(val, num_elem, elem_size); 00401 } 00402 00403 void 00404 D4StreamUnMarshaller::get_vector_float32(char *val, int64_t num_elem) 00405 { 00406 #if !USE_XDR_FOR_IEEE754_ENCODING 00407 assert(std::numeric_limits<float>::is_iec559); 00408 assert(val); 00409 assert(num_elem >= 0); 00410 assert(!(num_elem & 0x6000000000000000)); // 0x 60 00 --> 0110 0000 00411 00412 int64_t bytes = num_elem << 2; 00413 00414 d_in.read(val, bytes); 00415 00416 if (d_twiddle_bytes) 00417 m_twidle_vector_elements(val, num_elem, sizeof(dods_float32)); 00418 00419 #else 00420 if (type == dods_float32_c && !std::numeric_limits<float>::is_iec559) { 00421 // If not using IEEE 754, use XDR to get it that way. 00422 m_deserialize_reals(val, num, 4, type); 00423 } 00424 else if (type == dods_float64_c && !std::numeric_limits<double>::is_iec559) { 00425 m_deserialize_reals(val, num, 8, type); 00426 } 00427 else { 00428 d_in.read(val, num * width); 00429 if (d_twiddle_bytes) 00430 m_twidle_vector_elements(val, num, width); 00431 } 00432 #endif 00433 } 00434 00435 void 00436 D4StreamUnMarshaller::get_vector_float64(char *val, int64_t num_elem) 00437 { 00438 #if !USE_XDR_FOR_IEEE754_ENCODING 00439 assert(std::numeric_limits<float>::is_iec559); 00440 assert(val); 00441 assert(num_elem >= 0); 00442 assert(!(num_elem & 0x7000000000000000)); // 0x 70 00 --> 0111 0000 00443 00444 int64_t bytes = num_elem << 3; 00445 00446 d_in.read(val, bytes); 00447 00448 if (d_twiddle_bytes) 00449 m_twidle_vector_elements(val, num_elem, sizeof(dods_float64)); 00450 00451 #else 00452 if (type == dods_float32_c && !std::numeric_limits<float>::is_iec559) { 00453 // If not using IEEE 754, use XDR to get it that way. 00454 m_deserialize_reals(val, num, 4, type); 00455 } 00456 else if (type == dods_float64_c && !std::numeric_limits<double>::is_iec559) { 00457 m_deserialize_reals(val, num, 8, type); 00458 } 00459 else { 00460 d_in.read(val, num * width); 00461 if (d_twiddle_bytes) 00462 m_twidle_vector_elements(val, num, width); 00463 } 00464 #endif 00465 } 00466 00467 void 00468 D4StreamUnMarshaller::dump(ostream &strm) const 00469 { 00470 strm << DapIndent::LMarg << "D4StreamUnMarshaller::dump - (" 00471 << (void *)this << ")" << endl ; 00472 } 00473 00474 } // namespace libdap 00475