/usr/include/libdap/chunked_istream.h is in libdap-dev 3.15.1-7.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | // -*- mode: c++; c-basic-offset:4 -*-
// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.
// Copyright (c) 2013 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
//
// Portions of this code were taken verbatim from Josuttis,
// "The C++ Standard Library," p.672
#ifndef _chunked_istream_h
#define _chunked_istream_h
#include "chunked_stream.h"
#include <stdint.h>
#include <streambuf>
#include <istream>
#include <stdexcept>
#include <string>
namespace libdap {
class chunked_inbuf: public std::streambuf {
private:
std::istream &d_is;
uint32_t d_buf_size; // Size of the data buffer
char *d_buffer; // data buffer
// In the original implementation of this class, the byte order of the data stream
// was passed in via constructors. When BYTE_ORDER_PREFIX is defined that is the
// case. However, when it is not defined, the byte order is read from the chunk
// header's high order byte (in bit position 2 - see chunked_stream.h). jhrg 11/24/13
bool d_twiddle_bytes; // receiver-makes-right encoding (byte order)...
bool d_set_twiddle;
// If an error chunk is read, save the message here
std::string d_error_message;
bool d_error;
/**
* @brief allocate the internal buffer.
* Allocate d_buf_size + putBack characters for the read buffer.
* @param size How much can the buffer hold? Does not include the putBack
* chars.
*/
void m_buffer_alloc() {
delete d_buffer;
d_buffer = new char[d_buf_size];
setg(d_buffer, // beginning of put back area
d_buffer, // read position
d_buffer); // end position
}
public:
/**
* @brief Build a chunked input buffer.
*
* This reads from a chunked stream, extracting an entire chunk and storing it in a
* buffer in one operation. If the chunked_inbuf reads a chunk header that indicates
* the next chunk is going be bigger than its current buffer size, the object will
* make the buffer larger. This object support 128 characters of 'put back' space. Since
* DAP4 uses receiver makes right, the buffer must be told if it should 'twiddle' the
* header size information. In DAP4 the byte order is sent using a one-byte code _before_
* the chunked transmission starts.
*
* @note In the current implementation, the byte order of the sender is read from the
* first chunk header. The method twiddle_bytes() returns false until the first chunk is
* read, then it returns the correct value. Only the first chunk_header is tested for the
* byte order flag; all subsequent chunks are assumed to use the same byte order.
*
* @param is Use this as a data source
* @param size The size of the input buffer. This should match the likely chunk size.
* If it is smaller than a chunk, it will be resized.
* @param twiddle_bytes Should the header bytes be twiddled? True if this host and the
* send use a different byte-order. The sender's byte order must be sent out-of-band.
*/
#if BYTE_ORDER_PREFIX
chunked_inbuf(std::istream &is, int size, bool twiddle_bytes = false)
: d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(twiddle_bytes), d_error(false) {
if (d_buf_size & CHUNK_TYPE_MASK)
throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff");
m_buffer_alloc();
}
#else
chunked_inbuf(std::istream &is, int size)
: d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(false), d_set_twiddle(false), d_error(false) {
if (d_buf_size & CHUNK_TYPE_MASK)
throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff");
m_buffer_alloc();
}
#endif
virtual ~chunked_inbuf() {
delete d_buffer;
}
int_type read_next_chunk();
int bytes_in_buffer() const { return (egptr() - gptr()); }
// d_twiddle_bytes is false initially and is set to the correct value
// once the first chunk is read.
bool twiddle_bytes() const { return d_twiddle_bytes; }
bool error() const { return d_error; }
std::string error_message() const { return d_error_message; }
protected:
virtual int_type underflow();
virtual std::streamsize xsgetn(char* s, std::streamsize num);
};
class chunked_istream: public std::istream {
protected:
chunked_inbuf d_cbuf;
public:
#if BYTE_ORDER_PREFIX
chunked_istream(std::istream &is, int size, bool twiddle_bytes = false) : std::istream(&d_cbuf), d_cbuf(is, size, twiddle_bytes) { }
#else
chunked_istream(std::istream &is, int size) : std::istream(&d_cbuf), d_cbuf(is, size) { }
#endif
int read_next_chunk() { return d_cbuf.read_next_chunk(); }
/**
* How many bytes have been read from the stream and are now in the internal buffer?
* @return Number of buffered bytes.
*/
int bytes_in_buffer() const { return d_cbuf.bytes_in_buffer(); }
/**
* Should the receiver twiddle the bytes to match the local machine's byte order?
* Since DAP4 uses 'receiver makes right' encoding, the onus is on the client to
* reorder the bytes if it is, e.g., a big endian machine reading data from a little
* endian server.
*
* @return True if the client (caller) should swap bytes in multi-byte integers, etc.,
* and false if not. This does not directly tell the endian nature of the remote server,
* although that can be inferred.
*/
bool twiddle_bytes() const { return d_cbuf.twiddle_bytes(); }
bool error() const { return d_cbuf.error(); }
std::string error_message() const { return d_cbuf.error_message(); }
};
}
#endif // _chunked_istream_h
|