libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
D4StreamMarshaller.cc
Go to the documentation of this file.
1// D4StreamMarshaller.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#include <cstring>
32
33#include <iomanip>
34#include <iostream>
35#include <limits>
36#include <sstream>
37
38// #define DODS_DEBUG 1
39
40#ifdef HAVE_PTHREAD_H
41#include <pthread.h>
42#endif
43
44#include "D4StreamMarshaller.h"
45#ifdef USE_POSIX_THREADS
46#include "MarshallerThread.h"
47#endif
48
49#if USE_XDR_FOR_IEEE754_ENCODING
50#include "XDRUtils.h"
51#include "util.h"
52#endif
53
54#include "DapIndent.h"
55#include "debug.h"
56
57using namespace std;
58
59namespace libdap {
60
61#if 0
62// We decided to use int64_t to represent sizes of both arrays and strings,
63// So this code is not used. jhrg 10/4/13
64
65// From the Google protobuf library
66inline uint8_t* WriteVarint64ToArrayInline(uint64_t value, uint8_t* target) {
67 // Splitting into 32-bit pieces gives better performance on 32-bit
68 // processors.
69 uint32_t part0 = static_cast<uint32_t>(value );
70 uint32_t part1 = static_cast<uint32_t>(value >> 28);
71 uint32_t part2 = static_cast<uint32_t>(value >> 56);
72
73 int size;
74
75 // Here we can't really optimize for small numbers, since the value is
76 // split into three parts. Checking for numbers < 128, for instance,
77 // would require three comparisons, since you'd have to make sure part1
78 // and part2 are zero. However, if the caller is using 64-bit integers,
79 // it is likely that they expect the numbers to often be very large, so
80 // we probably don't want to optimize for small numbers anyway. Thus,
81 // we end up with a hard coded binary search tree...
82 if (part2 == 0) {
83 if (part1 == 0) {
84 if (part0 < (1 << 14)) {
85 if (part0 < (1 << 7)) {
86 size = 1; goto size1;
87 } else {
88 size = 2; goto size2;
89 }
90 } else {
91 if (part0 < (1 << 21)) {
92 size = 3; goto size3;
93 } else {
94 size = 4; goto size4;
95 }
96 }
97 } else {
98 if (part1 < (1 << 14)) {
99 if (part1 < (1 << 7)) {
100 size = 5; goto size5;
101 } else {
102 size = 6; goto size6;
103 }
104 } else {
105 if (part1 < (1 << 21)) {
106 size = 7; goto size7;
107 } else {
108 size = 8; goto size8;
109 }
110 }
111 }
112 } else {
113 if (part2 < (1 << 7)) {
114 size = 9; goto size9;
115 } else {
116 size = 10; goto size10;
117 }
118 }
119
120 // GOOGLE_LOG(FATAL) << "Can't get here.";
121
122 size10: target[9] = static_cast<uint8_t>((part2 >> 7) | 0x80);
123 size9 : target[8] = static_cast<uint8_t>((part2 ) | 0x80);
124 size8 : target[7] = static_cast<uint8_t>((part1 >> 21) | 0x80);
125 size7 : target[6] = static_cast<uint8_t>((part1 >> 14) | 0x80);
126 size6 : target[5] = static_cast<uint8_t>((part1 >> 7) | 0x80);
127 size5 : target[4] = static_cast<uint8_t>((part1 ) | 0x80);
128 size4 : target[3] = static_cast<uint8_t>((part0 >> 21) | 0x80);
129 size3 : target[2] = static_cast<uint8_t>((part0 >> 14) | 0x80);
130 size2 : target[1] = static_cast<uint8_t>((part0 >> 7) | 0x80);
131 size1 : target[0] = static_cast<uint8_t>((part0 ) | 0x80);
132
133 target[size-1] &= 0x7F;
134 return target + size;
135}
136#endif
137
138#if USE_XDR_FOR_IEEE754_ENCODING
139void D4StreamMarshaller::m_serialize_reals(char *val, unsigned int num, int width, Type type) {
140 dods_uint64 size = num * width;
141
142 char *buf = new char[size];
143 XDR xdr;
144 xdrmem_create(&xdr, buf.data(), size, XDR_ENCODE);
145 try {
146 if (!xdr_array(&xdr, &val, (unsigned int *)&num, size, width, XDRUtils::xdr_coder(type)))
147 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float64 array");
148
149 if (xdr_getpos(&xdr) != size)
150 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float64 array");
151
152 // If this is a little-endian host, twiddle the bytes
153 static bool twiddle_bytes = !is_host_big_endian();
154 if (twiddle_bytes) {
155 if (width == 4) {
156 dods_float32 *lbuf = reinterpret_cast<dods_float32 *>(buf.data());
157 while (num--) {
158 dods_int32 *i = reinterpret_cast<dods_int32 *>(lbuf++);
159 *i = bswap_32(*i);
160 }
161 } else { // width == 8
162 dods_float64 *lbuf = reinterpret_cast<dods_float64 *>(buf.data());
163 while (num--) {
164 dods_int64 *i = reinterpret_cast<dods_int64 *>(lbuf++);
165 *i = bswap_64(*i);
166 }
167 }
168 }
169#ifdef USE_POSIX_THREADS
170 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
171
172 tm->increment_child_thread_count();
173 tm->start_thread(MarshallerThread::write_thread, d_out, buf, size);
174
175 // The child thread will delete buf when it's done
176 xdr_destroy(&xdr);
177#else
178 d_out.write(buf.data(), size);
179 xdr_destroy(&xdr);
180 delete[] buf;
181#endif
182 } catch (...) {
183 xdr_destroy(&xdr);
184 delete[] buf;
185
186 throw;
187 }
188}
189#endif
190
198D4StreamMarshaller::D4StreamMarshaller(ostream &out, bool write_data) : d_out(out), d_write_data(write_data), tm(0) {
199 assert(sizeof(std::streamsize) >= sizeof(int64_t));
200
201#if USE_XDR_FOR_IEEE754_ENCODING
202 // XDR is used if the call std::numeric_limits<double>::is_iec559()
203 // returns false indicating that the compiler is not using IEEE 754.
204 // If it is, we just write out the bytes.
205 xdrmem_create(&d_scalar_sink, d_ieee754_buf, sizeof(dods_float64), XDR_ENCODE);
206#endif
207
208#ifdef USE_POSIX_THREADS
209 tm = new MarshallerThread;
210#endif
211
212 // This will cause exceptions to be thrown on i/o errors. The exception
213 // will be ostream::failure
214 out.exceptions(ostream::failbit | ostream::badbit);
215}
216
218#if USE_XDR_FOR_IEEE754_ENCODING
219 xdr_destroy(&d_scalar_sink);
220#endif
221
222 delete tm;
223}
224
227void D4StreamMarshaller::reset_checksum() { d_checksum.Reset(); }
228
240 ostringstream oss;
241 oss.setf(ios::hex, ios::basefield);
242 oss << setfill('0') << setw(8) << d_checksum.GetCrc32();
243
244 return oss.str();
245}
246
254 Crc32::checksum chk = d_checksum.GetCrc32();
255#ifdef USE_POSIX_THREADS
256 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
257#endif
258 d_out.write(reinterpret_cast<char *>(&chk), sizeof(Crc32::checksum));
259}
260
265void D4StreamMarshaller::checksum_update(const void *data, unsigned long len) {
266 d_checksum.AddData(reinterpret_cast<const uint8_t *>(data), len);
267}
268
270 checksum_update(&val, sizeof(dods_byte));
271
272 if (d_write_data) {
273 DBG(std::cerr << "put_byte: " << val << std::endl);
274#ifdef USE_POSIX_THREADS
275 // make sure that a child thread is not writing to d_out.
276 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
277#endif
278 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_byte));
279 }
280}
281
283 checksum_update(&val, sizeof(dods_int8));
284
285 if (d_write_data) {
286 DBG(std::cerr << "put_int8: " << val << std::endl);
287#ifdef USE_POSIX_THREADS
288 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
289#endif
290 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_int8));
291 }
292}
293
295 checksum_update(&val, sizeof(dods_int16));
296
297 if (d_write_data) {
298#ifdef USE_POSIX_THREADS
299 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
300#endif
301 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_int16));
302 }
303}
304
306 checksum_update(&val, sizeof(dods_int32));
307
308 if (d_write_data) {
309#ifdef USE_POSIX_THREADS
310 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
311#endif
312 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_int32));
313 }
314}
315
317 checksum_update(&val, sizeof(dods_int64));
318
319 if (d_write_data) {
320#ifdef USE_POSIX_THREADS
321 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
322#endif
323 d_out.write(reinterpret_cast<const char *>(&val), sizeof(dods_int64));
324 }
325}
326
328#if !USE_XDR_FOR_IEEE754_ENCODING
329 assert(std::numeric_limits<float>::is_iec559);
330
331 checksum_update(&val, sizeof(dods_float32));
332
333 if (d_write_data) {
334#ifdef USE_POSIX_THREADS
335 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
336#endif
337 d_out.write(reinterpret_cast<const char *>(&val), sizeof(dods_float32));
338 }
339
340#else
341 // This code uses XDR to convert from a local representation to IEEE754;
342 // The extra 'twiddle' operation makes the byte-order correct for this
343 // host should it not be big-endian. Also note the assert() at the
344 // start of the method.
345
346 if (d_write_data) {
347 if (std::numeric_limits<float>::is_iec559) {
348#ifdef USE_POSIX_THREADS
349 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
350#endif
351 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_float32));
352 } else {
353 if (!xdr_setpos(&d_scalar_sink, 0))
354 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float32 variable");
355
356 if (!xdr_float(&d_scalar_sink, &val))
357 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float32 variable");
358
359 if (xdr_getpos(&d_scalar_sink) != sizeof(dods_float32))
360 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float32 variable");
361
362 // If this is a little-endian host, twiddle the bytes
363 static bool twiddle_bytes = !is_host_big_endian();
364 if (twiddle_bytes) {
365 dods_int32 *i = reinterpret_cast<dods_int32 *>(&d_ieee754_buf);
366 *i = bswap_32(*i);
367 }
368#ifdef USE_POSIX_THREADS
369 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
370#endif
371 d_out.write(d_ieee754_buf, sizeof(dods_float32));
372 }
373 }
374#endif
375}
376
378#if !USE_XDR_FOR_IEEE754_ENCODING
379 assert(std::numeric_limits<double>::is_iec559);
380
381 checksum_update(&val, sizeof(dods_float64));
382
383 if (d_write_data) {
384#ifdef USE_POSIX_THREADS
385 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
386#endif
387 d_out.write(reinterpret_cast<const char *>(&val), sizeof(dods_float64));
388 }
389
390#else
391 // See the comment above in put_float32()
392 if (d_write_data) {
393 if (std::numeric_limits<double>::is_iec559) {
394#ifdef USE_POSIX_THREADS
395 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
396#endif
397 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_float64));
398 }
399 } else {
400 if (!xdr_setpos(&d_scalar_sink, 0))
401 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float64 variable");
402
403 if (!xdr_double(&d_scalar_sink, &val))
404 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float64 variable");
405
406 if (xdr_getpos(&d_scalar_sink) != sizeof(dods_float64))
407 throw InternalErr(__FILE__, __LINE__, "Error serializing a Float64 variable");
408
409 // If this is a little-endian host, twiddle the bytes
410 static bool twiddle_bytes = !is_host_big_endian();
411 if (twiddle_bytes) {
412 dods_int64 *i = reinterpret_cast<dods_int64 *>(&d_ieee754_buf);
413 *i = bswap_64(*i);
414 }
415
416#ifdef USE_POSIX_THREADS
417 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
418#endif
419 d_out.write(d_ieee754_buf, sizeof(dods_float64));
420 }
421}
422#endif
423}
424
426 checksum_update(&val, sizeof(dods_uint16));
427
428 if (d_write_data) {
429#ifdef USE_POSIX_THREADS
430 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
431#endif
432 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_uint16));
433 }
434}
435
437 checksum_update(&val, sizeof(dods_uint32));
438
439 if (d_write_data) {
440#ifdef USE_POSIX_THREADS
441 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
442#endif
443 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_uint32));
444 }
445}
446
448 checksum_update(&val, sizeof(dods_uint64));
449
450 if (d_write_data) {
451#ifdef USE_POSIX_THREADS
452 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
453#endif
454 d_out.write(reinterpret_cast<char *>(&val), sizeof(dods_uint64));
455 }
456}
457
466void D4StreamMarshaller::put_count(int64_t count) {
467#ifdef USE_POSIX_THREADS
468 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
469#endif
470 d_out.write(reinterpret_cast<const char *>(&count), sizeof(int64_t));
471}
472
473void D4StreamMarshaller::put_str(const string &val) {
474 checksum_update(val.c_str(), val.length());
475
476 if (d_write_data) {
477 int64_t len = val.length();
478#ifdef USE_POSIX_THREADS
479 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
480#endif
481 d_out.write(reinterpret_cast<const char *>(&len), sizeof(int64_t));
482 d_out.write(val.data(), val.length());
483 }
484}
485
486void D4StreamMarshaller::put_url(const string &val) { put_str(val); }
487
488void D4StreamMarshaller::put_opaque_dap4(const char *val, int64_t len) {
489 assert(val);
490 assert(len >= 0);
491
492 checksum_update(val, len);
493
494 if (d_write_data) {
495#ifdef USE_POSIX_THREADS
496 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
497
498 d_out.write(reinterpret_cast<const char *>(&len), sizeof(int64_t));
499
500 char *byte_buf = new char[len];
501 memcpy(byte_buf, val, len);
502
503 tm->increment_child_thread_count();
504 tm->start_thread(MarshallerThread::write_thread, d_out, byte_buf, len);
505#else
506 d_out.write(reinterpret_cast<const char *>(&len), sizeof(int64_t));
507 d_out.write(val, len);
508#endif
509 }
510}
511
517void D4StreamMarshaller::put_vector(char *val, int64_t num_bytes) {
518 assert(val);
519 assert(num_bytes >= 0);
520
521 checksum_update(val, num_bytes);
522
523 if (d_write_data) {
524#ifdef USE_POSIX_THREADS
525 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
526
527 char *buf = new char[num_bytes];
528 memcpy(buf, val, num_bytes);
529
530 tm->increment_child_thread_count();
531 tm->start_thread(MarshallerThread::write_thread, d_out, buf, num_bytes);
532#else
533 d_out.write(val, num_bytes);
534#endif
535 }
536}
537
538void D4StreamMarshaller::put_vector(char *val, int64_t num_elem, int elem_size) {
539 assert(val);
540 assert(num_elem >= 0);
541 assert(elem_size > 0);
542
543 int64_t bytes;
544
545 switch (elem_size) {
546 case 1:
547 assert(!"Don't call this method for bytes, use put_vector(val, bytes) instead");
548 bytes = num_elem;
549 break;
550 case 2:
551 // Don't bother testing the sign bit
552 assert(!(num_elem & 0x4000000000000000)); // 0x 40 00 --> 0100 0000
553 bytes = num_elem << 1;
554 break;
555 case 4:
556 assert(!(num_elem & 0x6000000000000000)); // 0x 60 00 --> 0110 0000
557 bytes = num_elem << 2;
558 break;
559 case 8:
560 assert(!(num_elem & 0x7000000000000000)); // 0111 0000
561 bytes = num_elem << 3;
562 break;
563 default:
564 bytes = num_elem * elem_size;
565 break;
566 }
567
568 checksum_update(val, bytes);
569
570 if (d_write_data) {
571#ifdef USE_POSIX_THREADS
572 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
573
574 char *buf = new char[bytes];
575 memcpy(buf, val, bytes);
576
577 tm->increment_child_thread_count();
578 tm->start_thread(MarshallerThread::write_thread, d_out, buf, bytes);
579#else
580 d_out.write(val, bytes);
581#endif
582 }
583}
584
594void D4StreamMarshaller::put_vector_float32(char *val, int64_t num_elem) {
595#if !USE_XDR_FOR_IEEE754_ENCODING
596
597 assert(std::numeric_limits<float>::is_iec559);
598 assert(val);
599 assert(num_elem >= 0);
600 // sizeof() a 32-bit float is 4, so we're going to send 4 * num_elem bytes, so
601 // make sure that doesn't overflow a 63-bit integer (the max positive value in
602 // a signed int64; use 1110 0000 0.. (0xe000 ...) to mask for non-zero bits
603 // to test that num can be multiplied by 4. A
604 assert(!(num_elem & 0xe000000000000000));
605
606 num_elem = num_elem << 2; // num_elem is now the number of bytes
607
608 checksum_update(val, num_elem);
609
610 if (d_write_data) {
611#ifdef USE_POSIX_THREADS
612 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
613
614 char *buf = new char[num_elem];
615 memcpy(buf, val, num_elem);
616
617 tm->increment_child_thread_count();
618 tm->start_thread(MarshallerThread::write_thread, d_out, buf, num_elem);
619#else
620 d_out.write(val, num_elem);
621#endif
622 }
623
624#else
625 assert(val);
626 assert(num_elem >= 0);
627 // sizeof() a 32-bit float is 4, so we're going to send 4 * num_elem bytes, so
628 // make sure that doesn't overflow a 63-bit integer (the max positive value in
629 // a signed int64; use 1110 0000 0.. (0xe000 ...) to mask for non-zero bits
630 // to test that num can be multiplied by 4. A
631 assert(!(num_elem & 0xe000000000000000));
632
633 int64_t bytes = num_elem << 2; // num_elem is now the number of bytes
634
635 checksum_update(val, bytes);
636
637 if (d_write_data) {
638 if (!std::numeric_limits<float>::is_iec559) {
639 // If not using IEEE 754, use XDR to get it that way.
640 m_serialize_reals(val, num_elem, 4, type);
641 } else {
642#ifdef USE_POSIX_THREADS
643 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
644
645 char *buf = new char[bytes];
646 memcpy(buf, val, bytes);
647
648 tm->increment_child_thread_count();
649 tm->start_thread(MarshallerThread::write_thread, d_out, buf, bytes);
650#else
651 d_out.write(val, bytes);
652#endif
653 }
654 }
655#endif
656}
657
666void D4StreamMarshaller::put_vector_float64(char *val, int64_t num_elem) {
667#if !USE_XDR_FOR_IEEE754_ENCODING
668
669 assert(std::numeric_limits<double>::is_iec559);
670 assert(val);
671 assert(num_elem >= 0);
672 // See comment above
673 assert(!(num_elem & 0xf000000000000000));
674
675 num_elem = num_elem << 3; // num_elem is now the number of bytes
676
677 checksum_update(val, num_elem);
678
679 if (d_write_data) {
680#ifdef USE_POSIX_THREADS
681 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
682
683 char *buf = new char[num_elem];
684 memcpy(buf, val, num_elem);
685
686 tm->increment_child_thread_count();
687 tm->start_thread(MarshallerThread::write_thread, d_out, buf, num_elem);
688#else
689 d_out.write(val, num_elem);
690#endif
691 }
692#else
693 assert(val);
694 assert(num_elem >= 0);
695 // sizeof() a 32-bit float is 4, so we're going to send 4 * num_elem bytes, so
696 // make sure that doesn't overflow a 63-bit integer (the max positive value in
697 // a signed int64; use 1110 0000 0.. (0xe000 ...) to mask for non-zero bits
698 // to test that num can be multiplied by 4. A
699 assert(!(num_elem & 0xe000000000000000));
700
701 int64_t bytes = num_elem << 3; // num_elem is now the number of bytes
702
703 checksum_update(val, bytes);
704
705 if (d_write_data) {
706 if (!std::numeric_limits<double>::is_iec559) {
707 // If not using IEEE 754, use XDR to get it that way.
708 m_serialize_reals(val, num_elem, 8, type);
709 } else {
710#ifdef USE_POSIX_THREADS
711 Locker lock(tm->get_mutex(), tm->get_cond(), tm->get_child_thread_count());
712
713 char *buf = new char[bytes];
714 memcpy(buf, val, bytes);
715
716 tm->increment_child_thread_count();
717 tm->start_thread(MarshallerThread::write_thread, d_out, buf, bytes);
718#else
719 d_out.write(val, bytes);
720#endif
721 }
722 }
723#endif
724}
725
726void D4StreamMarshaller::put_vector_part(char *val, unsigned int num, int width, Type type) {
727 assert(val);
728 assert(num >= 0);
729 assert(width > 0);
730
731 switch (type) {
732 case dods_byte_c:
733 case dods_char_c:
734 case dods_int8_c:
735 case dods_uint8_c:
736 put_vector(val, num);
737 break;
738
739 case dods_int16_c:
740 case dods_uint16_c:
741 case dods_int32_c:
742 case dods_uint32_c:
743 case dods_int64_c:
744 case dods_uint64_c:
745 put_vector(val, num, width);
746 break;
747
748 case dods_enum_c:
749 if (width == 1)
750 put_vector(val, num);
751 else
752 put_vector(val, num, width);
753 break;
754
755 case dods_float32_c:
756 put_vector_float32(val, num);
757 break;
758
759 case dods_float64_c:
760 put_vector_float32(val, num);
761 break;
762
763 case dods_str_c:
764 case dods_url_c:
765 throw InternalErr(__FILE__, __LINE__, "Array of String should not be passed to put_vector.");
766
767 case dods_array_c:
768 throw InternalErr(__FILE__, __LINE__, "Array of Array not allowed.");
769
770 case dods_opaque_c:
771 case dods_structure_c:
772 case dods_sequence_c:
773 throw InternalErr(__FILE__, __LINE__, "Array of String should not be passed to put_vector.");
774
775 case dods_grid_c:
776 throw InternalErr(__FILE__, __LINE__, "Grid is not part of DAP4.");
777
778 default:
779 throw InternalErr(__FILE__, __LINE__, "Unknown datatype.");
780 }
781}
782
783void D4StreamMarshaller::dump(ostream &strm) const {
784 strm << DapIndent::LMarg << "D4StreamMarshaller::dump - (" << (void *)this << ")" << endl;
785}
786
787} // namespace libdap
uint32_t checksum
Definition crc.h:45
virtual void put_uint16(dods_uint16 val)
virtual void put_checksum()
Write the checksum Write the checksum for the data sent since the last call to reset_checksum() to th...
virtual void put_int32(dods_int32 val)
virtual void put_opaque_dap4(const char *val, int64_t len)
virtual void put_uint64(dods_uint64 val)
virtual void put_vector_float32(char *val, int64_t num_elem)
Write a fixed size vector.
virtual void put_vector_part(char *, unsigned int, int, Type)
virtual void put_byte(dods_byte val)
virtual void put_str(const string &val)
virtual void put_vector(char *val, int64_t num_bytes)
Write a fixed size vector.
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
virtual void put_count(int64_t count)
virtual void put_int8(dods_int8 val)
virtual void put_int64(dods_int64 val)
virtual void put_url(const string &val)
virtual void put_int16(dods_int16 val)
virtual void put_uint32(dods_uint32 val)
virtual void checksum_update(const void *data, unsigned long len)
virtual void put_float64(dods_float64 val)
virtual void put_vector_float64(char *val, int64_t num_elem)
Write a fixed size vector of float64s.
virtual void put_float32(dods_float32 val)
static ostream & LMarg(ostream &strm)
Definition DapIndent.cc:61
A class for software fault reporting.
Definition InternalErr.h:61
static void * write_thread(void *arg)
static xdrproc_t xdr_coder(const Type &t)
Returns a function used to encode elements of an array.
Definition XDRUtils.cc:137
#define DBG(x)
Definition debug.h:58
top level DAP object to house generic methods
Definition AISConnect.cc:30
Type
Identifies the data type.
Definition Type.h:94
@ dods_sequence_c
Definition Type.h:108
@ dods_uint32_c
Definition Type.h:100
@ dods_int16_c
Definition Type.h:97
@ dods_byte_c
Definition Type.h:96
@ dods_int32_c
Definition Type.h:99
@ dods_url_c
Definition Type.h:104
@ dods_int8_c
Definition Type.h:115
@ dods_float32_c
Definition Type.h:101
@ dods_char_c
Definition Type.h:114
@ dods_int64_c
Definition Type.h:118
@ dods_uint64_c
Definition Type.h:119
@ dods_uint16_c
Definition Type.h:98
@ dods_float64_c
Definition Type.h:102
@ dods_enum_c
Definition Type.h:120
@ dods_grid_c
Definition Type.h:111
@ dods_uint8_c
Definition Type.h:116
@ dods_str_c
Definition Type.h:103
@ dods_structure_c
Definition Type.h:106
@ dods_array_c
Definition Type.h:107
@ dods_opaque_c
Definition Type.h:121
bool is_host_big_endian()
Does this host use big-endian byte order?
Definition util.cc:94
uint64_t dods_uint64
uint32_t dods_uint32
uint16_t dods_uint16