basic_streambuf.hpp
Go to the documentation of this file.
00001 //
00002 // basic_streambuf.hpp
00003 // ~~~~~~~~~~~~~~~~~~~
00004 //
00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
00006 //
00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00009 //
00010 
00011 #ifndef ASIO_BASIC_STREAMBUF_HPP
00012 #define ASIO_BASIC_STREAMBUF_HPP
00013 
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017 
00018 #include "asio/detail/push_options.hpp"
00019 
00020 #include "asio/detail/push_options.hpp"
00021 #include <algorithm>
00022 #include <limits>
00023 #include <memory>
00024 #include <stdexcept>
00025 #include <streambuf>
00026 #include <vector>
00027 #include "asio/detail/pop_options.hpp"
00028 
00029 #include "asio/buffer.hpp"
00030 #include "asio/detail/noncopyable.hpp"
00031 
00032 namespace asio {
00033 
00035 template <typename Allocator = std::allocator<char> >
00036 class basic_streambuf
00037   : public std::streambuf,
00038     private noncopyable
00039 {
00040 public:
00041 #if defined(GENERATING_DOCUMENTATION)
00042 
00043   typedef implementation_defined const_buffers_type;
00044 
00046   typedef implementation_defined mutable_buffers_type;
00047 #else
00048   typedef asio::const_buffers_1 const_buffers_type;
00049   typedef asio::mutable_buffers_1 mutable_buffers_type;
00050 #endif
00051 
00053   explicit basic_streambuf(
00054       std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
00055       const Allocator& allocator = Allocator())
00056     : max_size_(max_size),
00057       buffer_(allocator)
00058   {
00059     std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
00060     buffer_.resize((std::max<std::size_t>)(pend, 1));
00061     setg(&buffer_[0], &buffer_[0], &buffer_[0]);
00062     setp(&buffer_[0], &buffer_[0] + pend);
00063   }
00064 
00066   std::size_t size() const
00067   {
00068     return pptr() - gptr();
00069   }
00070 
00072   std::size_t max_size() const
00073   {
00074     return max_size_;
00075   }
00076 
00078   const_buffers_type data() const
00079   {
00080     return asio::buffer(asio::const_buffer(gptr(),
00081           (pptr() - gptr()) * sizeof(char_type)));
00082   }
00083 
00085   mutable_buffers_type prepare(std::size_t size)
00086   {
00087     reserve(size);
00088     return asio::buffer(asio::mutable_buffer(
00089           pptr(), size * sizeof(char_type)));
00090   }
00091 
00093   void commit(std::size_t n)
00094   {
00095     if (pptr() + n > epptr())
00096       n = epptr() - pptr();
00097     pbump(static_cast<int>(n));
00098   }
00099 
00101   void consume(std::size_t n)
00102   {
00103     if (gptr() + n > pptr())
00104       n = pptr() - gptr();
00105     gbump(static_cast<int>(n));
00106   }
00107 
00108 protected:
00109   enum { buffer_delta = 128 };
00110 
00111   int_type underflow()
00112   {
00113     if (gptr() < pptr())
00114     {
00115       setg(&buffer_[0], gptr(), pptr());
00116       return traits_type::to_int_type(*gptr());
00117     }
00118     else
00119     {
00120       return traits_type::eof();
00121     }
00122   }
00123 
00124   int_type overflow(int_type c)
00125   {
00126     if (!traits_type::eq_int_type(c, traits_type::eof()))
00127     {
00128       if (pptr() == epptr())
00129       {
00130         std::size_t buffer_size = pptr() - gptr();
00131         if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
00132         {
00133           reserve(max_size_ - buffer_size);
00134         }
00135         else
00136         {
00137           reserve(buffer_delta);
00138         }
00139       }
00140 
00141       *pptr() = traits_type::to_char_type(c);
00142       pbump(1);
00143       return c;
00144     }
00145 
00146     return traits_type::not_eof(c);
00147   }
00148 
00149   void reserve(std::size_t n)
00150   {
00151     // Get current stream positions as offsets.
00152     std::size_t gnext = gptr() - &buffer_[0];
00153     std::size_t gend = egptr() - &buffer_[0];
00154     std::size_t pnext = pptr() - &buffer_[0];
00155     std::size_t pend = epptr() - &buffer_[0];
00156 
00157     // Check if there is already enough space in the put area.
00158     if (n <= pend - pnext)
00159     {
00160       return;
00161     }
00162 
00163     // Shift existing contents of get area to start of buffer.
00164     if (gnext > 0)
00165     {
00166       std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
00167       gend -= gnext;
00168       pnext -= gnext;
00169     }
00170 
00171     // Ensure buffer is large enough to hold at least the specified size.
00172     if (n > pend - pnext)
00173     {
00174       if (n <= max_size_ && pnext <= max_size_ - n)
00175       {
00176         buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
00177       }
00178       else
00179       {
00180         throw std::length_error("asio::streambuf too long");
00181       }
00182     }
00183 
00184     // Update stream positions.
00185     setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
00186     setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
00187   }
00188 
00189 private:
00190   std::size_t max_size_;
00191   std::vector<char_type, Allocator> buffer_;
00192 };
00193 
00194 } // namespace asio
00195 
00196 #include "asio/detail/pop_options.hpp"
00197 
00198 #endif // ASIO_BASIC_STREAMBUF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39