chunked_istream.h
// -*- 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;
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:
#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(); }
int bytes_in_buffer() const { return d_cbuf.bytes_in_buffer(); }
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
libdap::chunked_inbuf::read_next_chunk
int_type read_next_chunk()
Read a chunk Normally the chunked nature of a chunked_istream/chunked_inbuf is hidden from the caller...
Definition: chunked_istream.cc:341
libdap::chunked_istream
Definition: chunked_istream.h:137
libdap
Definition: AlarmHandler.h:35
libdap::chunked_inbuf
Definition: chunked_istream.h:42
libdap::chunked_inbuf::underflow
virtual int_type underflow()
Insert new characters into the buffer This specialization of underflow is called when the gptr() is a...
Definition: chunked_istream.cc:85
libdap::chunked_inbuf::xsgetn
virtual std::streamsize xsgetn(char *s, std::streamsize num)
Read a block of data This specialization of xsgetn() reads num bytes and puts them in s first reading...
Definition: chunked_istream.cc:185
libdap::chunked_inbuf::chunked_inbuf
chunked_inbuf(std::istream &is, int size)
Build a chunked input buffer.
Definition: chunked_istream.h:107
libdap::chunked_istream::bytes_in_buffer
int bytes_in_buffer() const
Definition: chunked_istream.h:153
libdap::chunked_istream::twiddle_bytes
bool twiddle_bytes() const
Definition: chunked_istream.h:165