libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
D4StreamUnMarshaller.cc
Go to the documentation of this file.
1// D4StreamUnMarshaller.cc
2
3// -*- mode: c++; c-basic-offset:4 -*-
4
5// This file is part of libdap, A C++ implementation of the OPeNDAP Data
6// Access Protocol.
7
8// Copyright (c) 2012 OPeNDAP, Inc.
9// Author: James Gallagher <jgallagher@opendap.org>
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Lesser General Public
13// License as published by the Free Software Foundation; either
14// version 2.1 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24//
25// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26
27#include "config.h"
28
29#include <byteswap.h>
30#include <cassert>
31
32#include <iomanip>
33#include <iostream>
34#include <limits>
35#include <sstream>
36#include <string>
37
38// #define DODS_DEBUG2 1
39// #define DODS_DEBUG 1
40
42#include "DapIndent.h"
43#include "InternalErr.h"
44#include "debug.h"
45#include "util.h"
46
47namespace libdap {
48
59D4StreamUnMarshaller::D4StreamUnMarshaller(istream &in, bool twiddle_bytes) : d_in(in), d_twiddle_bytes(twiddle_bytes) {
60 assert(sizeof(std::streamsize) >= sizeof(int64_t));
61
62#if USE_XDR_FOR_IEEE754_ENCODING
63 // XDR is used to handle transforming non-ieee754 reals, nothing else.
64 xdrmem_create(&d_source, d_buf, sizeof(dods_float64), XDR_DECODE);
65#endif
66
67 // This will cause exceptions to be thrown on i/o errors. The exception
68 // will be ostream::failure
69 d_in.exceptions(istream::failbit | istream::badbit);
70}
71
78D4StreamUnMarshaller::D4StreamUnMarshaller(istream &in) : d_in(in), d_twiddle_bytes(false) {
79 assert(sizeof(std::streamsize) >= sizeof(int64_t));
80
81#if USE_XDR_FOR_IEEE754_ENCODING
82 // XDR is used to handle transforming non-ieee754 reals, nothing else.
83 xdrmem_create(&d_source, d_buf, sizeof(dods_float64), XDR_DECODE);
84#endif
85
86 // This will cause exceptions to be thrown on i/o errors. The exception
87 // will be ostream::failure
88 d_in.exceptions(istream::failbit | istream::badbit);
89}
90
92#if USE_XDR_FOR_IEEE754_ENCODING
93 xdr_destroy(&d_source);
94#endif
95}
96
99 d_in.read(reinterpret_cast<char *>(&c), sizeof(Crc32::checksum));
100
101 return c;
102}
103
105 ostringstream oss;
106 oss.setf(ios::hex, ios::basefield);
107 oss << setfill('0') << setw(8) << get_checksum();
108
109 return oss.str();
110}
111
112void D4StreamUnMarshaller::get_byte(dods_byte &val) { d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_byte)); }
113
114void D4StreamUnMarshaller::get_int8(dods_int8 &val) { d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_int8)); }
115
117 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_int16));
118 if (d_twiddle_bytes)
119 val = bswap_16(val);
120}
121
123 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_int32));
124 if (d_twiddle_bytes)
125 val = bswap_32(val);
126}
127
129 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_int64));
130 if (d_twiddle_bytes)
131 val = bswap_64(val);
132}
133
135#if !USE_XDR_FOR_IEEE754_ENCODING
136 assert(std::numeric_limits<float>::is_iec559);
137
138 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_float32));
139 if (d_twiddle_bytes) {
140 dods_int32 *i = reinterpret_cast<dods_int32 *>(&val);
141 *i = bswap_32(*i);
142 }
143
144#else
145 if (std::numeric_limits<float>::is_iec559) {
146 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_float32));
147 if (d_twiddle_bytes) {
148 dods_int32 *i = reinterpret_cast<dods_int32 *>(&val);
149 *i = bswap_32(*i);
150 }
151
152 } else {
153 xdr_setpos(&d_source, 0);
154 d_in.read(d_buf, sizeof(dods_float32));
155
156 if (!xdr_float(&d_source, &val))
157 throw Error("Network I/O Error. Could not read float 64 data.");
158 }
159#endif
160}
161
163#if !USE_XDR_FOR_IEEE754_ENCODING
164 assert(std::numeric_limits<double>::is_iec559);
165
166 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_float64));
167 if (d_twiddle_bytes) {
168 dods_int64 *i = reinterpret_cast<dods_int64 *>(&val);
169 *i = bswap_64(*i);
170 }
171
172#else
173 if (std::numeric_limits<float>::is_iec559) {
174 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_float64));
175 if (d_twiddle_bytes) {
176 dods_int64 *i = reinterpret_cast<dods_int64 *>(&val);
177 *i = bswap_64(*i);
178 }
179 } else {
180 xdr_setpos(&d_source, 0);
181 d_in.read(d_buf, sizeof(dods_float64));
182
183 if (!xdr_double(&d_source, &val))
184 throw Error("Network I/O Error. Could not read float 64 data.");
185 }
186#endif
187}
188
190 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_uint16));
191 if (d_twiddle_bytes)
192 val = bswap_16(val);
193}
194
196 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_uint32));
197 if (d_twiddle_bytes)
198 val = bswap_32(val);
199}
200
202 d_in.read(reinterpret_cast<char *>(&val), sizeof(dods_uint64));
203 if (d_twiddle_bytes)
204 val = bswap_64(val);
205}
206
208 int64_t len;
209 d_in.read(reinterpret_cast<char *>(&len), sizeof(int64_t));
210
211 val.resize(len);
212 d_in.read(&val[0], len);
213}
214
215void D4StreamUnMarshaller::get_url(string &val) { get_str(val); }
216
226 int64_t count;
227 d_in.read(reinterpret_cast<char *>(&count), sizeof(count));
228 return count;
229}
230
238void D4StreamUnMarshaller::get_opaque_dap4(char **val, int64_t &len) {
239 // len = get_length_prefix();
240 d_in.read(reinterpret_cast<char *>(&len), sizeof(len));
241
242 *val = new char[len];
243 d_in.read(*val, len);
244}
245
246void D4StreamUnMarshaller::get_opaque_dap4(vector<uint8_t> &val) {
247 // len = get_length_prefix();
248 int64_t len;
249 d_in.read(reinterpret_cast<char *>(&len), sizeof(len));
250
251 val.resize(len);
252 d_in.read(reinterpret_cast<char *>(val.data()), len);
253}
254
255void D4StreamUnMarshaller::get_vector(char *val, int64_t bytes) { d_in.read(val, bytes); }
256
257#if USE_XDR_FOR_IEEE754_ENCODING
258void D4StreamUnMarshaller::m_deserialize_reals(char *val, int64_t num, int width, Type type) {
259 int64_t size = num * width;
260 // char *buf = (char*)malloc(size); jhrg 7/23/13
261 vector<char> buf(size);
262 XDR xdr;
263 xdrmem_create(&xdr, buf.data(), size, XDR_DECODE);
264 try {
265 xdr_setpos(&d_source, 0);
266 d_in.read(buf.data(), size);
267
268 if (!xdr_array(&xdr, &val, (unsigned int *)&num, size, width, XDRUtils::xdr_coder(type)))
269 throw InternalErr(__FILE__, __LINE__, "Error deserializing a Float64 array");
270
271 if (xdr_getpos(&xdr) != size)
272 throw InternalErr(__FILE__, __LINE__, "Error deserializing a Float64 array");
273 } catch (...) {
274 xdr_destroy(&xdr);
275 throw;
276 }
277 xdr_destroy(&xdr);
278}
279#endif
280
281void D4StreamUnMarshaller::m_twidle_vector_elements(char *vals, int64_t num, int width) {
282 switch (width) {
283 case 2: {
284 dods_int16 *local = reinterpret_cast<dods_int16 *>(vals);
285 while (num--) {
286 *local = bswap_16(*local);
287 local++;
288 }
289 break;
290 }
291 case 4: {
292 dods_int32 *local = reinterpret_cast<dods_int32 *>(vals);
293 ;
294 while (num--) {
295 *local = bswap_32(*local);
296 local++;
297 }
298 break;
299 }
300 case 8: {
301 dods_int64 *local = reinterpret_cast<dods_int64 *>(vals);
302 ;
303 while (num--) {
304 *local = bswap_64(*local);
305 local++;
306 }
307 break;
308 }
309 default:
310 throw InternalErr(__FILE__, __LINE__, "Unrecognized word size.");
311 }
312}
313
314void D4StreamUnMarshaller::get_vector(char *val, int64_t num_elem, int elem_size) {
315 assert(std::numeric_limits<float>::is_iec559);
316 assert(std::numeric_limits<double>::is_iec559);
317 assert(val);
318 assert(num_elem >= 0);
319 assert(elem_size > 0);
320
321 int64_t bytes;
322
323 switch (elem_size) {
324 case 1:
325 assert(!"Don't call this method for bytes, use put_vector(val, bytes) instead");
326 bytes = num_elem;
327 break;
328 case 2:
329 // Don't bother testing the sign bit
330 assert(!(num_elem & 0x4000000000000000)); // 0x 40 00 --> 0100 0000
331 bytes = num_elem << 1;
332 break;
333 case 4:
334 assert(!(num_elem & 0x6000000000000000)); // 0x 60 00 --> 0110 0000
335 bytes = num_elem << 2;
336 break;
337 case 8:
338 assert(!(num_elem & 0x7000000000000000)); // 0111 0000
339 bytes = num_elem << 3;
340 break;
341 default:
342 bytes = num_elem * elem_size;
343 break;
344 }
345
346 d_in.read(val, bytes);
347
348 if (d_twiddle_bytes)
349 m_twidle_vector_elements(val, num_elem, elem_size);
350}
351
352void D4StreamUnMarshaller::get_vector_float32(char *val, int64_t num_elem) {
353#if !USE_XDR_FOR_IEEE754_ENCODING
354 assert(std::numeric_limits<float>::is_iec559);
355 assert(val);
356 assert(num_elem >= 0);
357 assert(!(num_elem & 0x6000000000000000)); // 0x 60 00 --> 0110 0000
358
359 int64_t bytes = num_elem << 2;
360
361 d_in.read(val, bytes);
362
363 if (d_twiddle_bytes)
364 m_twidle_vector_elements(val, num_elem, sizeof(dods_float32));
365
366#else
367 if (type == dods_float32_c && !std::numeric_limits<float>::is_iec559) {
368 // If not using IEEE 754, use XDR to get it that way.
369 m_deserialize_reals(val, num, 4, type);
370 } else if (type == dods_float64_c && !std::numeric_limits<double>::is_iec559) {
371 m_deserialize_reals(val, num, 8, type);
372 } else {
373 d_in.read(val, num * width);
374 if (d_twiddle_bytes)
375 m_twidle_vector_elements(val, num, width);
376 }
377#endif
378}
379
380void D4StreamUnMarshaller::get_vector_float64(char *val, int64_t num_elem) {
381#if !USE_XDR_FOR_IEEE754_ENCODING
382 assert(std::numeric_limits<float>::is_iec559);
383 assert(val);
384 assert(num_elem >= 0);
385 assert(!(num_elem & 0x7000000000000000)); // 0x 70 00 --> 0111 0000
386
387 int64_t bytes = num_elem << 3;
388
389 d_in.read(val, bytes);
390
391 if (d_twiddle_bytes)
392 m_twidle_vector_elements(val, num_elem, sizeof(dods_float64));
393
394#else
395 if (type == dods_float32_c && !std::numeric_limits<float>::is_iec559) {
396 // If not using IEEE 754, use XDR to get it that way.
397 m_deserialize_reals(val, num, 4, type);
398 } else if (type == dods_float64_c && !std::numeric_limits<double>::is_iec559) {
399 m_deserialize_reals(val, num, 8, type);
400 } else {
401 d_in.read(val, num * width);
402 if (d_twiddle_bytes)
403 m_twidle_vector_elements(val, num, width);
404 }
405#endif
406}
407
408void D4StreamUnMarshaller::dump(ostream &strm) const {
409 strm << DapIndent::LMarg << "D4StreamUnMarshaller::dump - (" << (void *)this << ")" << endl;
410}
411
412} // namespace libdap
uint32_t checksum
Definition crc.h:45
virtual void get_byte(dods_byte &val)
virtual void get_vector_float64(char *val, int64_t num_elem)
virtual void get_uint64(dods_uint64 &val)
virtual void get_int32(dods_int32 &val)
virtual void get_vector_float32(char *val, int64_t num_elem)
virtual void get_uint16(dods_uint16 &val)
virtual void get_str(string &val)
virtual void get_float64(dods_float64 &val)
virtual void get_url(string &val)
virtual void get_opaque_dap4(char **val, int64_t &len)
virtual void get_int16(dods_int16 &val)
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
virtual void get_vector(char **, unsigned int &, Vector &)
virtual void get_int8(dods_int8 &val)
virtual void get_float32(dods_float32 &val)
virtual void get_int64(dods_int64 &val)
virtual void get_uint32(dods_uint32 &val)
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
A class for error processing.
Definition Error.h:92
A class for software fault reporting.
Definition InternalErr.h:61
static xdrproc_t xdr_coder(const Type &t)
Returns a function used to encode elements of an array.
Definition XDRUtils.cc:137
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94
@ dods_float32_c
Definition Type.h:101
@ dods_float64_c
Definition Type.h:102
uint64_t dods_uint64
uint32_t dods_uint32
uint16_t dods_uint16