libdap  Updated for version 3.20.3
libdap4 is an implementation of OPeNDAP's DAP protocol.
chunked_istream.h
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2013 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 //
25 // Portions of this code were taken verbatim from Josuttis,
26 // "The C++ Standard Library," p.672
27 
28 #ifndef _chunked_istream_h
29 #define _chunked_istream_h
30 
31 #include "chunked_stream.h"
32 
33 #include <stdint.h>
34 
35 #include <streambuf>
36 #include <istream>
37 #include <stdexcept>
38 #include <string>
39 
40 namespace libdap {
41 
42 class chunked_inbuf: public std::streambuf {
43 private:
44  std::istream &d_is;
45 
46  uint32_t d_buf_size; // Size of the data buffer
47  char *d_buffer; // data buffer
48 
49  // In the original implementation of this class, the byte order of the data stream
50  // was passed in via constructors. When BYTE_ORDER_PREFIX is defined that is the
51  // case. However, when it is not defined, the byte order is read from the chunk
52  // header's high order byte (in bit position 2 - see chunked_stream.h). jhrg 11/24/13
53 
54  bool d_twiddle_bytes; // receiver-makes-right encoding (byte order)...
55  bool d_set_twiddle;
56 
57  // If an error chunk is read, save the message here
58  std::string d_error_message;
59  bool d_error;
60 
67  void m_buffer_alloc() {
68  delete[] d_buffer;
69  d_buffer = new char[d_buf_size];
70  setg(d_buffer, // beginning of put back area
71  d_buffer, // read position
72  d_buffer); // end position
73  }
74 
75 public:
98 #if BYTE_ORDER_PREFIX
99  chunked_inbuf(std::istream &is, int size, bool twiddle_bytes = false)
100  : d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(twiddle_bytes), d_error(false) {
101  if (d_buf_size & CHUNK_TYPE_MASK)
102  throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff");
103 
104  m_buffer_alloc();
105  }
106 #else
107  chunked_inbuf(std::istream &is, int size)
108  : d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(false), d_set_twiddle(false), d_error(false) {
109  if (d_buf_size & CHUNK_TYPE_MASK)
110  throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff");
111 
112  m_buffer_alloc();
113  }
114 #endif
115 
116  virtual ~chunked_inbuf() {
117  delete[] d_buffer;
118  }
119 
120  int_type read_next_chunk();
121 
122  int bytes_in_buffer() const { return (egptr() - gptr()); }
123 
124  // d_twiddle_bytes is false initially and is set to the correct value
125  // once the first chunk is read.
126  bool twiddle_bytes() const { return d_twiddle_bytes; }
127 
128  bool error() const { return d_error; }
129  std::string error_message() const { return d_error_message; }
130 
131 protected:
132  virtual int_type underflow();
133 
134  virtual std::streamsize xsgetn(char* s, std::streamsize num);
135 };
136 
137 class chunked_istream: public std::istream {
138 protected:
139  chunked_inbuf d_cbuf;
140 public:
141 #if BYTE_ORDER_PREFIX
142  chunked_istream(std::istream &is, int size, bool twiddle_bytes = false) : std::istream(&d_cbuf), d_cbuf(is, size, twiddle_bytes) { }
143 #else
144  chunked_istream(std::istream &is, int size) : std::istream(&d_cbuf), d_cbuf(is, size) { }
145 #endif
146 
147  int read_next_chunk() { return d_cbuf.read_next_chunk(); }
148 
153  int bytes_in_buffer() const { return d_cbuf.bytes_in_buffer(); }
154 
165  bool twiddle_bytes() const { return d_cbuf.twiddle_bytes(); }
166  bool error() const { return d_cbuf.error(); }
167  std::string error_message() const { return d_cbuf.error_message(); }
168 };
169 
170 }
171 
172 #endif // _chunked_istream_h
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:183
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
Definition: chunked_istream.h:42
libdap
top level DAP object to house generic methods
Definition: AlarmHandler.h:36
libdap::chunked_istream::bytes_in_buffer
int bytes_in_buffer() const
Definition: chunked_istream.h:153
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::twiddle_bytes
bool twiddle_bytes() const
Definition: chunked_istream.h:165
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