aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/apache/avro/api/buffer/Buffer.hh
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.ru>2022-02-10 16:45:08 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:08 +0300
commit4e839db24a3bbc9f1c610c43d6faaaa99824dcca (patch)
tree506dac10f5df94fab310584ee51b24fc5a081c22 /contrib/libs/apache/avro/api/buffer/Buffer.hh
parent2d37894b1b037cf24231090eda8589bbb44fb6fc (diff)
downloadydb-4e839db24a3bbc9f1c610c43d6faaaa99824dcca.tar.gz
Restoring authorship annotation for <thegeorg@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/apache/avro/api/buffer/Buffer.hh')
-rw-r--r--contrib/libs/apache/avro/api/buffer/Buffer.hh1052
1 files changed, 526 insertions, 526 deletions
diff --git a/contrib/libs/apache/avro/api/buffer/Buffer.hh b/contrib/libs/apache/avro/api/buffer/Buffer.hh
index 7d7aaf8679..b2a04dd683 100644
--- a/contrib/libs/apache/avro/api/buffer/Buffer.hh
+++ b/contrib/libs/apache/avro/api/buffer/Buffer.hh
@@ -1,526 +1,526 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef avro_Buffer_hh__
-#define avro_Buffer_hh__
-
-#ifndef _WIN32
-#include <sys/uio.h>
-#endif
-#include <vector>
-
-#include "../Config.hh"
-#include "detail/BufferDetail.hh"
-#include "detail/BufferDetailIterator.hh"
-
-/**
- * \file Buffer.hh
- *
- * \brief Definitions for InputBuffer and OutputBuffer classes
- *
- **/
-
-namespace avro {
-
-class OutputBuffer;
-class InputBuffer;
-
-
-/**
- * The OutputBuffer (write-only buffer)
- *
- * Use cases for OutputBuffer
- *
- * - write message to buffer using ostream class or directly
- * - append messages to headers
- * - building up streams of messages via append
- * - converting to read-only buffers for sending
- * - extracting parts of the messages into read-only buffers
- *
- * -# ASIO access:
- * - write to a buffer(s) by asio using iterator
- * - convert to read buffer for deserializing
- *
- * OutputBuffer is assignable and copy-constructable. On copy or assignment,
- * only a pointer is copied, so the two resulting copies are identical, so
- * modifying one will modify both.
- **/
-
-class AVRO_DECL OutputBuffer
-{
-
- public:
-
- typedef detail::size_type size_type;
- typedef detail::data_type data_type;
-
- /**
- * The asio library expects a const_iterator (the const-ness refers to the
- * fact that the underlying avro of buffers will not be modified, even
- * though the data in those buffers is being modified). The iterator
- * provides the list of addresses an operation can write to.
- **/
-
- typedef detail::OutputBufferIterator const_iterator;
-
- /**
- * Default constructor. Will pre-allocate at least the requested size, but
- * can grow larger on demand.
- *
- * Destructor uses the default, which resets a shared pointer, deleting the
- * underlying data if no other copies of exist.
- *
- * Copy and assignment operators are not explicitly provided because the
- * default ones work fine. The default makes only a shallow copy, so the
- * copies will refer to the same memory. This is required by asio
- * functions, which will implicitly make copies for asynchronous
- * operations. Therefore, the user must be careful that if they create
- * multiple copies of the same OutputBuffer, only one is being modified
- * otherwise undefined behavior may occur.
- *
- **/
-
- OutputBuffer(size_type reserveSize = 0) :
- pimpl_(new detail::BufferImpl)
- {
- if(reserveSize) {
- reserve(reserveSize);
- }
- }
-
- /**
- * Reserve enough space for a wroteTo() operation. When using writeTo(),
- * the buffer will grow dynamically as needed. But when using the iterator
- * to write (followed by wroteTo()), data may only be written to the space
- * available, so this ensures there is enough room in the buffer before
- * the write operation.
- **/
-
- void reserve(size_type reserveSize)
- {
- pimpl_->reserveFreeSpace(reserveSize);
- }
-
- /**
- * Write a block of data to the buffer. The buffer size will automatically
- * grow if the size is larger than what is currently free.
- **/
-
- size_type writeTo(const data_type *data, size_type size) {
- return pimpl_->writeTo(data, size);
- }
-
- /**
- * Write a single value to the buffer. The buffer size will automatically
- * grow if there is not room for the byte. The value must be a
- * "fundamental" type, e.g. int, float, etc. (otherwise use the other
- * writeTo tests).
- **/
-
- template<typename T>
- void writeTo(T val) {
- pimpl_->writeTo(val, std::is_fundamental<T>());
- }
-
- /**
- * Update the state of the buffer after writing through the iterator
- * interface. This function exists primarily for the boost:asio which
- * writes directly to the buffer using its iterator. In this case, the
- * internal state of the buffer does not reflect that the data was written
- * This informs the buffer how much data was written.
- *
- * The buffer does not automatically resize in this case, the bytes written
- * cannot exceed the amount of free space. Attempting to write more will
- * throw a std::length_error exception.
- **/
-
- size_type wroteTo(size_type size)
- {
- int wrote = 0;
- if(size) {
- if(size > freeSpace()) {
- throw std::length_error("Impossible to write more data than free space");
- }
- wrote = pimpl_->wroteTo(size);
- }
- return wrote;
- }
-
- /**
- * Does the buffer have any data?
- **/
-
- bool empty() const {
- return (pimpl_->size()==0);
- }
-
- /**
- * Returns the size of the buffer, in bytes.
- */
-
- size_type size() const {
- return pimpl_->size();
- }
-
- /**
- * Returns the current free space that is available to write to in the
- * buffer, in bytes. This is not a strict limit in size, as writeTo() can
- * automatically increase capacity if necessary.
- **/
-
- size_type freeSpace() const {
- return pimpl_->freeSpace();
- }
-
- /**
- * Appends the data in the argument to the end of this buffer. The
- * argument can be either an InputBuffer or OutputBuffer.
- *
- **/
-
- template <class BufferType>
- void append(const BufferType &buf) {
- // don't append an empty buffer
- if(buf.size()) {
- pimpl_->append(*(buf.pimpl_.get()));
- }
- }
-
- /**
- * Return an iterator pointing to the first data chunk of this buffer
- * that may be written to.
- **/
-
- const_iterator begin() const {
- return const_iterator(pimpl_->beginWrite());
- }
-
- /**
- * Return the end iterator for writing.
- **/
-
- const_iterator end() const {
- return const_iterator(pimpl_->endWrite());
- }
-
- /**
- * Discard any data in this buffer.
- **/
-
- void discardData()
- {
- pimpl_->discardData();
- }
-
- /**
- * Discard the specified number of bytes from this data, starting at the beginning.
- * Throws if the size is greater than the number of bytes.
- **/
-
- void discardData(size_t bytes)
- {
- if(bytes > 0) {
- if(bytes < pimpl_->size()) {
- pimpl_->discardData(bytes);
- }
- else if(bytes == pimpl_->size()) {
- pimpl_->discardData();
- }
- else {
- throw std::out_of_range("trying to discard more data than exists");
- }
- }
- }
-
- /**
- * Remove bytes from this buffer, starting from the beginning, and place
- * them into a new buffer. Throws if the number of requested bytes exceeds
- * the size of the buffer. Data and freeSpace in the buffer after bytes
- * remains in this buffer.
- **/
-
- InputBuffer extractData(size_type bytes);
-
- /**
- * Remove all bytes from this buffer, returning them in a new buffer.
- * After removing data, some freeSpace may remain in this buffer.
- **/
-
- InputBuffer extractData();
-
- /**
- * Clone this buffer, creating a copy that contains the same data.
- **/
-
- OutputBuffer clone() const
- {
- detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl(*pimpl_));
- return OutputBuffer(newImpl);
- }
-
- /**
- * Add unmanaged data to the buffer. The buffer will not automatically
- * free the data, but it will call the supplied function when the data is
- * no longer referenced by the buffer (or copies of the buffer).
- **/
-
- void appendForeignData(const data_type *data, size_type size, const detail::free_func &func) {
- pimpl_->appendForeignData(data, size, func);
- }
-
- /**
- * Returns the number of chunks that contain free space.
- **/
-
- int numChunks() const {
- return pimpl_->numFreeChunks();
- }
-
- /**
- * Returns the number of chunks that contain data
- **/
-
- int numDataChunks() const {
- return pimpl_->numDataChunks();
- }
-
- private:
-
- friend class InputBuffer;
- friend class BufferReader;
-
- explicit OutputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
- pimpl_(pimpl)
- { }
-
- detail::BufferImpl::SharedPtr pimpl_; ///< Must never be null.
-};
-
-/**
- * The InputBuffer (read-only buffer)
- *
- * InputBuffer is an immutable buffer which that may be constructed from an
- * OutputBuffer, or several of OutputBuffer's methods. Once the data is
- * transfered to an InputBuffer it cannot be modified, only read (via
- * BufferReader, istream, or its iterator).
- *
- * Assignments and copies are shallow copies.
- *
- * -# ASIO access: - iterate using const_iterator for sending messages
- *
- **/
-
-class AVRO_DECL InputBuffer
-{
-
- public:
-
- typedef detail::size_type size_type;
- typedef detail::data_type data_type;
-
- // needed for asio
- typedef detail::InputBufferIterator const_iterator;
-
- /**
- * Default InputBuffer creates an empty buffer.
- *
- * Copy/assignment functions use the default ones. They will do a shallow
- * copy, and because InputBuffer is immutable, the copies will be
- * identical.
- *
- * Destructor also uses the default, which resets a shared pointer,
- * deleting the underlying data if no other copies of exist.
- **/
-
- InputBuffer() :
- pimpl_(new detail::BufferImpl)
- { }
-
- /**
- * Construct an InputBuffer that contains the contents of an OutputBuffer.
- * The two buffers will have the same contents, but this copy will be
- * immutable, while the the OutputBuffer may still be written to.
- *
- * If you wish to move the data from the OutputBuffer to a new InputBuffer
- * (leaving only free space in the OutputBuffer),
- * OutputBuffer::extractData() will do this more efficiently.
- *
- * Implicit conversion is allowed.
- **/
-
- InputBuffer(const OutputBuffer &src) :
- pimpl_(new detail::BufferImpl(*src.pimpl_))
- { }
-
- /**
- * Does the buffer have any data?
- **/
-
- bool empty() const {
- return (pimpl_->size() == 0);
- }
-
- /**
- * Returns the size of the buffer, in bytes.
- **/
-
- size_type size() const {
- return pimpl_->size();
- }
-
- /**
- * Return an iterator pointing to the first data chunk of this buffer
- * that contains data.
- **/
-
- const_iterator begin() const {
- return const_iterator(pimpl_->beginRead());
- }
-
- /**
- * Return the end iterator.
- **/
-
- const_iterator end() const {
- return const_iterator(pimpl_->endRead());
- }
-
- /**
- * Returns the number of chunks containing data.
- **/
-
- int numChunks() const {
- return pimpl_->numDataChunks();
- }
-
-
- private:
-
- friend class OutputBuffer; // for append function
- friend class istreambuf;
- friend class BufferReader;
-
- explicit InputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
- pimpl_(pimpl)
- { }
-
- /**
- * Class to indicate that a copy of a OutputBuffer to InputBuffer should be
- * a shallow copy, used to enable reading of the contents of an
- * OutputBuffer without need to convert it to InputBuffer using a deep
- * copy. It is private and only used by BufferReader and istreambuf
- * classes.
- *
- * Writing to an OutputBuffer while it is being read may lead to undefined
- * behavior.
- **/
-
- class ShallowCopy {};
-
- /**
- * Make a shallow copy of an OutputBuffer in order to read it without
- * causing conversion overhead.
- **/
- InputBuffer(const OutputBuffer &src, const ShallowCopy &) :
- pimpl_(src.pimpl_)
- { }
-
- /**
- * Make a shallow copy of an InputBuffer. The default copy constructor
- * already provides shallow copy, this is just provided for generic
- * algorithms that wish to treat InputBuffer and OutputBuffer in the same
- * manner.
- **/
-
- InputBuffer(const InputBuffer &src, const ShallowCopy &) :
- pimpl_(src.pimpl_)
- { }
-
-
- detail::BufferImpl::ConstSharedPtr pimpl_; ///< Must never be null.
-};
-
-
-/*
- * Implementations of some OutputBuffer functions are inlined here
- * because InputBuffer definition was required before.
- */
-
-inline InputBuffer OutputBuffer::extractData()
-{
- detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
- if(pimpl_->size()) {
- pimpl_->extractData(*newImpl);
- }
- return InputBuffer(newImpl);
-}
-
-inline InputBuffer OutputBuffer::extractData(size_type bytes)
-{
- if(bytes > pimpl_->size()) {
- throw std::out_of_range("trying to extract more data than exists");
- }
-
- detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
- if(bytes > 0) {
- if(bytes < pimpl_->size()) {
- pimpl_->extractData(*newImpl, bytes);
- }
- else {
- pimpl_->extractData(*newImpl);
- }
- }
-
- return InputBuffer(newImpl);
-}
-
-#ifndef _WIN32
-/**
- * Create an array of iovec structures from the buffer. This utility is used
- * to support writev and readv function calls. The caller should ensure the
- * buffer object is not deleted while using the iovec vector.
- *
- * If the BufferType is an InputBuffer, the iovec will point to the data that
- * already exists in the buffer, for reading.
- *
- * If the BufferType is an OutputBuffer, the iovec will point to the free
- * space, which may be written to. Before writing, the caller should call
- * OutputBuffer::reserve() to create enough room for the desired write (which
- * can be verified by calling OutputBuffer::freeSpace()), and after writing,
- * they MUST call OutputBuffer::wroteTo(), otherwise the buffer will not know
- * the space is not free anymore.
- *
- **/
-
-template<class BufferType>
-inline void toIovec(BufferType &buf, std::vector<struct iovec> &iov)
-{
- const int chunks = buf.numChunks();
- iov.resize(chunks);
- typename BufferType::const_iterator iter = buf.begin();
- for (int i = 0; i < chunks; ++i) {
- iov[i].iov_base = const_cast<typename BufferType::data_type *>(iter->data());
- iov[i].iov_len = iter->size();
- ++iter;
- }
-}
-#endif
-
-} // namespace
-
-#endif
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef avro_Buffer_hh__
+#define avro_Buffer_hh__
+
+#ifndef _WIN32
+#include <sys/uio.h>
+#endif
+#include <vector>
+
+#include "../Config.hh"
+#include "detail/BufferDetail.hh"
+#include "detail/BufferDetailIterator.hh"
+
+/**
+ * \file Buffer.hh
+ *
+ * \brief Definitions for InputBuffer and OutputBuffer classes
+ *
+ **/
+
+namespace avro {
+
+class OutputBuffer;
+class InputBuffer;
+
+
+/**
+ * The OutputBuffer (write-only buffer)
+ *
+ * Use cases for OutputBuffer
+ *
+ * - write message to buffer using ostream class or directly
+ * - append messages to headers
+ * - building up streams of messages via append
+ * - converting to read-only buffers for sending
+ * - extracting parts of the messages into read-only buffers
+ *
+ * -# ASIO access:
+ * - write to a buffer(s) by asio using iterator
+ * - convert to read buffer for deserializing
+ *
+ * OutputBuffer is assignable and copy-constructable. On copy or assignment,
+ * only a pointer is copied, so the two resulting copies are identical, so
+ * modifying one will modify both.
+ **/
+
+class AVRO_DECL OutputBuffer
+{
+
+ public:
+
+ typedef detail::size_type size_type;
+ typedef detail::data_type data_type;
+
+ /**
+ * The asio library expects a const_iterator (the const-ness refers to the
+ * fact that the underlying avro of buffers will not be modified, even
+ * though the data in those buffers is being modified). The iterator
+ * provides the list of addresses an operation can write to.
+ **/
+
+ typedef detail::OutputBufferIterator const_iterator;
+
+ /**
+ * Default constructor. Will pre-allocate at least the requested size, but
+ * can grow larger on demand.
+ *
+ * Destructor uses the default, which resets a shared pointer, deleting the
+ * underlying data if no other copies of exist.
+ *
+ * Copy and assignment operators are not explicitly provided because the
+ * default ones work fine. The default makes only a shallow copy, so the
+ * copies will refer to the same memory. This is required by asio
+ * functions, which will implicitly make copies for asynchronous
+ * operations. Therefore, the user must be careful that if they create
+ * multiple copies of the same OutputBuffer, only one is being modified
+ * otherwise undefined behavior may occur.
+ *
+ **/
+
+ OutputBuffer(size_type reserveSize = 0) :
+ pimpl_(new detail::BufferImpl)
+ {
+ if(reserveSize) {
+ reserve(reserveSize);
+ }
+ }
+
+ /**
+ * Reserve enough space for a wroteTo() operation. When using writeTo(),
+ * the buffer will grow dynamically as needed. But when using the iterator
+ * to write (followed by wroteTo()), data may only be written to the space
+ * available, so this ensures there is enough room in the buffer before
+ * the write operation.
+ **/
+
+ void reserve(size_type reserveSize)
+ {
+ pimpl_->reserveFreeSpace(reserveSize);
+ }
+
+ /**
+ * Write a block of data to the buffer. The buffer size will automatically
+ * grow if the size is larger than what is currently free.
+ **/
+
+ size_type writeTo(const data_type *data, size_type size) {
+ return pimpl_->writeTo(data, size);
+ }
+
+ /**
+ * Write a single value to the buffer. The buffer size will automatically
+ * grow if there is not room for the byte. The value must be a
+ * "fundamental" type, e.g. int, float, etc. (otherwise use the other
+ * writeTo tests).
+ **/
+
+ template<typename T>
+ void writeTo(T val) {
+ pimpl_->writeTo(val, std::is_fundamental<T>());
+ }
+
+ /**
+ * Update the state of the buffer after writing through the iterator
+ * interface. This function exists primarily for the boost:asio which
+ * writes directly to the buffer using its iterator. In this case, the
+ * internal state of the buffer does not reflect that the data was written
+ * This informs the buffer how much data was written.
+ *
+ * The buffer does not automatically resize in this case, the bytes written
+ * cannot exceed the amount of free space. Attempting to write more will
+ * throw a std::length_error exception.
+ **/
+
+ size_type wroteTo(size_type size)
+ {
+ int wrote = 0;
+ if(size) {
+ if(size > freeSpace()) {
+ throw std::length_error("Impossible to write more data than free space");
+ }
+ wrote = pimpl_->wroteTo(size);
+ }
+ return wrote;
+ }
+
+ /**
+ * Does the buffer have any data?
+ **/
+
+ bool empty() const {
+ return (pimpl_->size()==0);
+ }
+
+ /**
+ * Returns the size of the buffer, in bytes.
+ */
+
+ size_type size() const {
+ return pimpl_->size();
+ }
+
+ /**
+ * Returns the current free space that is available to write to in the
+ * buffer, in bytes. This is not a strict limit in size, as writeTo() can
+ * automatically increase capacity if necessary.
+ **/
+
+ size_type freeSpace() const {
+ return pimpl_->freeSpace();
+ }
+
+ /**
+ * Appends the data in the argument to the end of this buffer. The
+ * argument can be either an InputBuffer or OutputBuffer.
+ *
+ **/
+
+ template <class BufferType>
+ void append(const BufferType &buf) {
+ // don't append an empty buffer
+ if(buf.size()) {
+ pimpl_->append(*(buf.pimpl_.get()));
+ }
+ }
+
+ /**
+ * Return an iterator pointing to the first data chunk of this buffer
+ * that may be written to.
+ **/
+
+ const_iterator begin() const {
+ return const_iterator(pimpl_->beginWrite());
+ }
+
+ /**
+ * Return the end iterator for writing.
+ **/
+
+ const_iterator end() const {
+ return const_iterator(pimpl_->endWrite());
+ }
+
+ /**
+ * Discard any data in this buffer.
+ **/
+
+ void discardData()
+ {
+ pimpl_->discardData();
+ }
+
+ /**
+ * Discard the specified number of bytes from this data, starting at the beginning.
+ * Throws if the size is greater than the number of bytes.
+ **/
+
+ void discardData(size_t bytes)
+ {
+ if(bytes > 0) {
+ if(bytes < pimpl_->size()) {
+ pimpl_->discardData(bytes);
+ }
+ else if(bytes == pimpl_->size()) {
+ pimpl_->discardData();
+ }
+ else {
+ throw std::out_of_range("trying to discard more data than exists");
+ }
+ }
+ }
+
+ /**
+ * Remove bytes from this buffer, starting from the beginning, and place
+ * them into a new buffer. Throws if the number of requested bytes exceeds
+ * the size of the buffer. Data and freeSpace in the buffer after bytes
+ * remains in this buffer.
+ **/
+
+ InputBuffer extractData(size_type bytes);
+
+ /**
+ * Remove all bytes from this buffer, returning them in a new buffer.
+ * After removing data, some freeSpace may remain in this buffer.
+ **/
+
+ InputBuffer extractData();
+
+ /**
+ * Clone this buffer, creating a copy that contains the same data.
+ **/
+
+ OutputBuffer clone() const
+ {
+ detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl(*pimpl_));
+ return OutputBuffer(newImpl);
+ }
+
+ /**
+ * Add unmanaged data to the buffer. The buffer will not automatically
+ * free the data, but it will call the supplied function when the data is
+ * no longer referenced by the buffer (or copies of the buffer).
+ **/
+
+ void appendForeignData(const data_type *data, size_type size, const detail::free_func &func) {
+ pimpl_->appendForeignData(data, size, func);
+ }
+
+ /**
+ * Returns the number of chunks that contain free space.
+ **/
+
+ int numChunks() const {
+ return pimpl_->numFreeChunks();
+ }
+
+ /**
+ * Returns the number of chunks that contain data
+ **/
+
+ int numDataChunks() const {
+ return pimpl_->numDataChunks();
+ }
+
+ private:
+
+ friend class InputBuffer;
+ friend class BufferReader;
+
+ explicit OutputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
+ pimpl_(pimpl)
+ { }
+
+ detail::BufferImpl::SharedPtr pimpl_; ///< Must never be null.
+};
+
+/**
+ * The InputBuffer (read-only buffer)
+ *
+ * InputBuffer is an immutable buffer which that may be constructed from an
+ * OutputBuffer, or several of OutputBuffer's methods. Once the data is
+ * transfered to an InputBuffer it cannot be modified, only read (via
+ * BufferReader, istream, or its iterator).
+ *
+ * Assignments and copies are shallow copies.
+ *
+ * -# ASIO access: - iterate using const_iterator for sending messages
+ *
+ **/
+
+class AVRO_DECL InputBuffer
+{
+
+ public:
+
+ typedef detail::size_type size_type;
+ typedef detail::data_type data_type;
+
+ // needed for asio
+ typedef detail::InputBufferIterator const_iterator;
+
+ /**
+ * Default InputBuffer creates an empty buffer.
+ *
+ * Copy/assignment functions use the default ones. They will do a shallow
+ * copy, and because InputBuffer is immutable, the copies will be
+ * identical.
+ *
+ * Destructor also uses the default, which resets a shared pointer,
+ * deleting the underlying data if no other copies of exist.
+ **/
+
+ InputBuffer() :
+ pimpl_(new detail::BufferImpl)
+ { }
+
+ /**
+ * Construct an InputBuffer that contains the contents of an OutputBuffer.
+ * The two buffers will have the same contents, but this copy will be
+ * immutable, while the the OutputBuffer may still be written to.
+ *
+ * If you wish to move the data from the OutputBuffer to a new InputBuffer
+ * (leaving only free space in the OutputBuffer),
+ * OutputBuffer::extractData() will do this more efficiently.
+ *
+ * Implicit conversion is allowed.
+ **/
+
+ InputBuffer(const OutputBuffer &src) :
+ pimpl_(new detail::BufferImpl(*src.pimpl_))
+ { }
+
+ /**
+ * Does the buffer have any data?
+ **/
+
+ bool empty() const {
+ return (pimpl_->size() == 0);
+ }
+
+ /**
+ * Returns the size of the buffer, in bytes.
+ **/
+
+ size_type size() const {
+ return pimpl_->size();
+ }
+
+ /**
+ * Return an iterator pointing to the first data chunk of this buffer
+ * that contains data.
+ **/
+
+ const_iterator begin() const {
+ return const_iterator(pimpl_->beginRead());
+ }
+
+ /**
+ * Return the end iterator.
+ **/
+
+ const_iterator end() const {
+ return const_iterator(pimpl_->endRead());
+ }
+
+ /**
+ * Returns the number of chunks containing data.
+ **/
+
+ int numChunks() const {
+ return pimpl_->numDataChunks();
+ }
+
+
+ private:
+
+ friend class OutputBuffer; // for append function
+ friend class istreambuf;
+ friend class BufferReader;
+
+ explicit InputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
+ pimpl_(pimpl)
+ { }
+
+ /**
+ * Class to indicate that a copy of a OutputBuffer to InputBuffer should be
+ * a shallow copy, used to enable reading of the contents of an
+ * OutputBuffer without need to convert it to InputBuffer using a deep
+ * copy. It is private and only used by BufferReader and istreambuf
+ * classes.
+ *
+ * Writing to an OutputBuffer while it is being read may lead to undefined
+ * behavior.
+ **/
+
+ class ShallowCopy {};
+
+ /**
+ * Make a shallow copy of an OutputBuffer in order to read it without
+ * causing conversion overhead.
+ **/
+ InputBuffer(const OutputBuffer &src, const ShallowCopy &) :
+ pimpl_(src.pimpl_)
+ { }
+
+ /**
+ * Make a shallow copy of an InputBuffer. The default copy constructor
+ * already provides shallow copy, this is just provided for generic
+ * algorithms that wish to treat InputBuffer and OutputBuffer in the same
+ * manner.
+ **/
+
+ InputBuffer(const InputBuffer &src, const ShallowCopy &) :
+ pimpl_(src.pimpl_)
+ { }
+
+
+ detail::BufferImpl::ConstSharedPtr pimpl_; ///< Must never be null.
+};
+
+
+/*
+ * Implementations of some OutputBuffer functions are inlined here
+ * because InputBuffer definition was required before.
+ */
+
+inline InputBuffer OutputBuffer::extractData()
+{
+ detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
+ if(pimpl_->size()) {
+ pimpl_->extractData(*newImpl);
+ }
+ return InputBuffer(newImpl);
+}
+
+inline InputBuffer OutputBuffer::extractData(size_type bytes)
+{
+ if(bytes > pimpl_->size()) {
+ throw std::out_of_range("trying to extract more data than exists");
+ }
+
+ detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
+ if(bytes > 0) {
+ if(bytes < pimpl_->size()) {
+ pimpl_->extractData(*newImpl, bytes);
+ }
+ else {
+ pimpl_->extractData(*newImpl);
+ }
+ }
+
+ return InputBuffer(newImpl);
+}
+
+#ifndef _WIN32
+/**
+ * Create an array of iovec structures from the buffer. This utility is used
+ * to support writev and readv function calls. The caller should ensure the
+ * buffer object is not deleted while using the iovec vector.
+ *
+ * If the BufferType is an InputBuffer, the iovec will point to the data that
+ * already exists in the buffer, for reading.
+ *
+ * If the BufferType is an OutputBuffer, the iovec will point to the free
+ * space, which may be written to. Before writing, the caller should call
+ * OutputBuffer::reserve() to create enough room for the desired write (which
+ * can be verified by calling OutputBuffer::freeSpace()), and after writing,
+ * they MUST call OutputBuffer::wroteTo(), otherwise the buffer will not know
+ * the space is not free anymore.
+ *
+ **/
+
+template<class BufferType>
+inline void toIovec(BufferType &buf, std::vector<struct iovec> &iov)
+{
+ const int chunks = buf.numChunks();
+ iov.resize(chunks);
+ typename BufferType::const_iterator iter = buf.begin();
+ for (int i = 0; i < chunks; ++i) {
+ iov[i].iov_base = const_cast<typename BufferType::data_type *>(iter->data());
+ iov[i].iov_len = iter->size();
+ ++iter;
+ }
+}
+#endif
+
+} // namespace
+
+#endif