libdap  Updated for version 3.17.0
chunked_ostream.h
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 _chunkedostream_h
00029 #define _chunkedostream_h
00030 
00031 #include "chunked_stream.h"
00032 
00033 #include <streambuf>
00034 #include <ostream>
00035 #include <stdexcept>      // std::out_of_range
00036 
00037 #include "util.h"
00038 
00039 namespace libdap {
00040 
00041 class chunked_ostream;
00042 
00053 class chunked_outbuf: public std::streambuf {
00054         friend class chunked_ostream;
00055 protected:
00056         std::ostream &d_os;                     // Write stuff here
00057         unsigned int d_buf_size;        // Size of the data buffer
00058         char *d_buffer;                         // Data buffer
00059         bool d_big_endian;
00060 
00061 public:
00062         chunked_outbuf(std::ostream &os, unsigned int buf_size) : d_os(os), d_buf_size(buf_size), d_buffer(0) {
00063                 if (d_buf_size & CHUNK_TYPE_MASK)
00064                         throw std::out_of_range("A chunked_outbuf (or chunked_ostream) was built using a buffer larger than 0x00ffffff");
00065 
00066                 d_big_endian = is_host_big_endian();
00067                 d_buffer = new char[buf_size];
00068                 // Trick: making the pointers think the buffer is one char smaller than it
00069                 // really is ensures that overflow() will be called when there's space for
00070                 // one more character.
00071                 setp(d_buffer, d_buffer + (buf_size - 1));
00072         }
00073 
00074         virtual ~chunked_outbuf() {
00075                 // call end_chunk() and not sync()
00076                 end_chunk();
00077 
00078                 delete[] d_buffer;
00079         }
00080 
00081 protected:
00082         // data_chunk and end_chunk might not be needed because they
00083         // are called via flush() and ~chunked_outbuf(), resp. jhrg 9/13/13
00084         int_type data_chunk();  // sync() and overflow() call this
00085         int_type end_chunk();
00086 
00087         int_type err_chunk(const std::string &msg);
00088 
00089         virtual std::streamsize xsputn(const char *s, std::streamsize num);
00090         // Manipulate the buffer pointers using pbump() after filling the buffer
00091         // and then call data_chunk(). Leave remainder in buffer. Or copy logic
00092         // for data_chunk() into loop in this code.
00093 
00094         virtual int_type overflow(int c);
00095         virtual int_type sync();
00096 };
00097 
00120 class chunked_ostream: public std::ostream {
00121 protected:
00122         chunked_outbuf d_cbuf;
00123 public:
00129         chunked_ostream(std::ostream &os, unsigned int buf_size) : std::ostream(&d_cbuf), d_cbuf(os, buf_size) { }
00130 
00139         int_type write_end_chunk() { return d_cbuf.end_chunk(); }
00140 
00149         int_type write_data_chunk() { return d_cbuf.data_chunk(); }
00150 
00159         int_type write_err_chunk(const std::string &msg) { return d_cbuf.err_chunk(msg); }
00160 };
00161 
00162 }
00163 
00164 #endif          // _chunkedostream_h