libdap
Updated for version 3.17.0
|
00001 // -*- mode: c++; c-basic-offset:4 -*- 00002 00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00004 // Access Protocol. 00005 00006 // Copyright (c) 2013 OPeNDAP, Inc. 00007 // Author: James Gallagher <jgallagher@opendap.org> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00024 // 00025 // Portions of this code were taken verbatim from Josuttis, 00026 // "The C++ Standard Library," p.672 00027 00028 #ifndef _chunked_istream_h 00029 #define _chunked_istream_h 00030 00031 #include "chunked_stream.h" 00032 00033 #include <stdint.h> 00034 00035 #include <streambuf> 00036 #include <istream> 00037 #include <stdexcept> 00038 #include <string> 00039 00040 namespace libdap { 00041 00042 class chunked_inbuf: public std::streambuf { 00043 private: 00044 std::istream &d_is; 00045 00046 uint32_t d_buf_size; // Size of the data buffer 00047 char *d_buffer; // data buffer 00048 00049 // In the original implementation of this class, the byte order of the data stream 00050 // was passed in via constructors. When BYTE_ORDER_PREFIX is defined that is the 00051 // case. However, when it is not defined, the byte order is read from the chunk 00052 // header's high order byte (in bit position 2 - see chunked_stream.h). jhrg 11/24/13 00053 00054 bool d_twiddle_bytes; // receiver-makes-right encoding (byte order)... 00055 bool d_set_twiddle; 00056 00057 // If an error chunk is read, save the message here 00058 std::string d_error_message; 00059 bool d_error; 00060 00067 void m_buffer_alloc() { 00068 delete d_buffer; 00069 d_buffer = new char[d_buf_size]; 00070 setg(d_buffer, // beginning of put back area 00071 d_buffer, // read position 00072 d_buffer); // end position 00073 } 00074 00075 public: 00098 #if BYTE_ORDER_PREFIX 00099 chunked_inbuf(std::istream &is, int size, bool twiddle_bytes = false) 00100 : d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(twiddle_bytes), d_error(false) { 00101 if (d_buf_size & CHUNK_TYPE_MASK) 00102 throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff"); 00103 00104 m_buffer_alloc(); 00105 } 00106 #else 00107 chunked_inbuf(std::istream &is, int size) 00108 : d_is(is), d_buf_size(size), d_buffer(0), d_twiddle_bytes(false), d_set_twiddle(false), d_error(false) { 00109 if (d_buf_size & CHUNK_TYPE_MASK) 00110 throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff"); 00111 00112 m_buffer_alloc(); 00113 } 00114 #endif 00115 00116 virtual ~chunked_inbuf() { 00117 delete d_buffer; 00118 } 00119 00120 int_type read_next_chunk(); 00121 00122 int bytes_in_buffer() const { return (egptr() - gptr()); } 00123 00124 // d_twiddle_bytes is false initially and is set to the correct value 00125 // once the first chunk is read. 00126 bool twiddle_bytes() const { return d_twiddle_bytes; } 00127 00128 bool error() const { return d_error; } 00129 std::string error_message() const { return d_error_message; } 00130 00131 protected: 00132 virtual int_type underflow(); 00133 00134 virtual std::streamsize xsgetn(char* s, std::streamsize num); 00135 }; 00136 00137 class chunked_istream: public std::istream { 00138 protected: 00139 chunked_inbuf d_cbuf; 00140 public: 00141 #if BYTE_ORDER_PREFIX 00142 chunked_istream(std::istream &is, int size, bool twiddle_bytes = false) : std::istream(&d_cbuf), d_cbuf(is, size, twiddle_bytes) { } 00143 #else 00144 chunked_istream(std::istream &is, int size) : std::istream(&d_cbuf), d_cbuf(is, size) { } 00145 #endif 00146 00147 int read_next_chunk() { return d_cbuf.read_next_chunk(); } 00148 00153 int bytes_in_buffer() const { return d_cbuf.bytes_in_buffer(); } 00154 00165 bool twiddle_bytes() const { return d_cbuf.twiddle_bytes(); } 00166 bool error() const { return d_cbuf.error(); } 00167 std::string error_message() const { return d_cbuf.error_message(); } 00168 }; 00169 00170 } 00171 00172 #endif // _chunked_istream_h