/usr/include/libdap/chunked_ostream.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 | // -*- 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 _chunkedostream_h
#define _chunkedostream_h
#include "chunked_stream.h"
#include <streambuf>
#include <ostream>
#include <stdexcept> // std::out_of_range
#include "util.h"
namespace libdap {
class chunked_ostream;
/**
* @brief output buffer for a chunked stream
* This performs buffered output encoding the data in the stream using
* the simple chunking protocol defined for DAP4's binary data transmission.
* Each block of data is prefixed by four bytes: A CHUNK TYPE byte followed
* by three bytes that are the CHUNK SIZE. There are three CHUNK TYPES:
* data, end and error, indicated by the code values 0x00, 0x01 and 0x02.
* The size of a chunk is limited to 2^24 data bytes + 4 bytes for the
* chunk header.
*/
class chunked_outbuf: public std::streambuf {
friend class chunked_ostream;
protected:
std::ostream &d_os; // Write stuff here
unsigned int d_buf_size; // Size of the data buffer
char *d_buffer; // Data buffer
bool d_big_endian;
public:
chunked_outbuf(std::ostream &os, unsigned int buf_size) : d_os(os), d_buf_size(buf_size), d_buffer(0) {
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");
d_big_endian = is_host_big_endian();
d_buffer = new char[buf_size];
// Trick: making the pointers think the buffer is one char smaller than it
// really is ensures that overflow() will be called when there's space for
// one more character.
setp(d_buffer, d_buffer + (buf_size - 1));
}
virtual ~chunked_outbuf() {
// call end_chunk() and not sync()
end_chunk();
delete[] d_buffer;
}
protected:
// data_chunk and end_chunk might not be needed because they
// are called via flush() and ~chunked_outbuf(), resp. jhrg 9/13/13
int_type data_chunk(); // sync() and overflow() call this
int_type end_chunk();
int_type err_chunk(const std::string &msg);
virtual std::streamsize xsputn(const char *s, std::streamsize num);
// Manipulate the buffer pointers using pbump() after filling the buffer
// and then call data_chunk(). Leave remainder in buffer. Or copy logic
// for data_chunk() into loop in this code.
virtual int_type overflow(int c);
virtual int_type sync();
};
/**
* @brief A C++ stream class for chunked data.
* This class uses the chunked_outbuf class to provide for chunked
* binary serialization of data as specified by DAP4. Information
* to be serialized is broken into 'chunks' that are no more than
* 2^24 bytes in length. Each chunk is prefixed by a 4 byte header
* that indicates the type of chunk and size (number of bytes in the
* chunk body). There are three types of chunk: Data; End; and Error.
* In normal operation, a DAP4 data document/response is serialized as
* a sequence of DATA chunks followed by one END chunk (which may be
* zero bytes in length). If, during serialization, an error is detected,
* the currently buffered (but not sent) data are discarded and an
* ERROR chunk is sent with an error message.
*
* This class sends the END chunk when its destructor is called.
*
* Calling flush() on the ostream object will force a DATA chunk to be
* sent with the currently buffered data. Normal operation is to wait
* for the buffer to fill before sending a DATA chunk.
*
* @see chunked_outbuf
*/
class chunked_ostream: public std::ostream {
protected:
chunked_outbuf d_cbuf;
public:
/**
* Get a chunked_ostream with a buffer.
* @note The buffer size must not be more than 2^24 bytes (0x00ffffff)
* @param buf_size The size of the buffer in bytes.
*/
chunked_ostream(std::ostream &os, unsigned int buf_size) : std::ostream(&d_cbuf), d_cbuf(os, buf_size) { }
/**
* @brief Send an end chunk.
* Normally, an end chunk is sent by closing the chunked_ostream, but this
* method can be used to force sending it without closing the stream. Subsequent
* calls to send data will send data chunks.
* @note An end chunk is sent when the stream is closed.
* @return EOF on error or the number of bytes sent in the chunk body.
*/
int_type write_end_chunk() { return d_cbuf.end_chunk(); }
/**
* @brief Send the current contents of the buffer as a data chunk.
* Normally, the chunked_ostream object waits until the buffer is full before sending
* the next data chunk. This will force a send with whatever is in the buffer (e.g.,
* the DMR text). Data added after this call will be sent in subsequent chunks.
* @note Calling flush() on the stream forces a data chunk to be sent.
* @return EOF on error, otherwise the number of bytes sent in the chunk body.
*/
int_type write_data_chunk() { return d_cbuf.data_chunk(); }
/**
* @brief Send an error message down the stream.
* When called, this method dumps all the data currently in the buffer and
* sends the error message text instead, using a chunk type of CHUNK_ERR. The
* write buffer is maintained, however, so the stream ibject can still be used.
* @param msg The error message text
* @return The number of bytes 'dumped' from the write buffer.
*/
int_type write_err_chunk(const std::string &msg) { return d_cbuf.err_chunk(msg); }
};
}
#endif // _chunkedostream_h
|