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