blob: 44e35dd013852cb1218541d73b5bcf5da85d963f [file] [log] [blame]
/*
* 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_BufferDetailIterator_hh__
#define avro_BufferDetailIterator_hh__
#include "BufferDetail.hh"
/**
* \file BufferDetailIterator.hh
*
* \brief The implementation details for the Buffer iterators.
**/
namespace avro {
namespace detail {
/**
* \brief Implements conversion from a chunk to asio::const_buffer
*
* Iterators for an InputBuffer will iterate over the avro of chunks, so
* internally they contain an iterator. But the iterator needs to be
* convertable to an asio buffer for use in boost::asio functions. This class
* wraps the iterator with a cast operator to do this conversion.
**/
struct InputIteratorHelper {
/// Construct a helper with an unnassigned iterator.
InputIteratorHelper() : iter_() {}
/// Construct a helper with an iterator.
explicit InputIteratorHelper(const BufferImpl::ChunkList::const_iterator &iter) : iter_(iter) {}
/// The location of valid data in this chunk.
const data_type *data() const {
return iter_->tellReadPos();
}
/// The size of valid data in this chunk.
size_type size() const {
return iter_->dataSize();
}
/// Conversion operator. It doesn't check for null, because the only
/// the only time the chunk should be null is when it's the iterator
/// end(), which should never be dereferenced anyway.
#ifdef HAVE_BOOST_ASIO
operator ConstAsioBuffer() const {
return ConstAsioBuffer(data(), size());
}
#endif
BufferImpl::ChunkList::const_iterator iter_; ///< the current iterator
};
/**
* \brief Implements conversion from a chunk to asio::buffer
*
* Iterators for an OutputBuffer will iterate over the avro of chunks, so
* internally they contain an iterator. But the iterator needs to be
* convertable to an asio buffer for use in boost::asio functions. This class
* wraps the iterator with a cast operator to do this conversion.
*/
struct OutputIteratorHelper {
/// Construct a helper with an unnassigned iterator.
OutputIteratorHelper() : iter_() {}
/// Construct a helper with an iterator.
explicit OutputIteratorHelper(const BufferImpl::ChunkList::const_iterator &iter) : iter_(iter) {}
/// The location of the first writable byte in this chunk.
data_type *data() const {
return iter_->tellWritePos();
}
/// The size of area that can be written in this chunk.
size_type size() const {
return iter_->freeSize();
}
/// Conversion operator. It doesn't check for null, because the only
/// the only time the chunk should be null is when it's the iterator
/// end(), which should never be dereferenced anyway.
#ifdef HAVE_BOOST_ASIO
operator MutableAsioBuffer() const {
return MutableAsioBuffer(data(), size());
}
#endif
BufferImpl::ChunkList::const_iterator iter_; ///< the current iterator
};
/**
* \brief Implements the iterator for Buffer, that iterates through the
* buffer's chunks.
**/
template<typename Helper>
class BufferIterator {
public:
typedef BufferIterator<Helper> this_type;
/**
* @name Typedefs
*
* STL iterators define the following declarations. According to
* boost::asio documentation, the library expects the iterator to be
* bidirectional, however this implements only the forward iterator type.
* So far this has not created any problems with asio, but may change if
* future versions of the asio require it.
**/
//@{
typedef std::forward_iterator_tag iterator_category; // this is a lie to appease asio
typedef Helper value_type;
typedef std::ptrdiff_t difference_type;
typedef value_type *pointer;
typedef value_type &reference;
//@}
/// Construct an unitialized iterator.
BufferIterator() : helper_() {}
/* The default implementations are good here
/// Copy constructor.
BufferIterator(const BufferIterator &src) :
helper_(src.helper_)
{ }
/// Assignment.
this_type& operator= (const this_type &rhs) {
helper_ = rhs.helper_;
return *this;
}
*/
/// Construct iterator at the position in the buffer's chunk list.
explicit BufferIterator(BufferImpl::ChunkList::const_iterator iter) : helper_(iter) {}
/// Dereference iterator, returns InputIteratorHelper or OutputIteratorHelper wrapper.
reference operator*() {
return helper_;
}
/// Dereference iterator, returns const InputIteratorHelper or OutputIteratorHelper wrapper.
const value_type &operator*() const {
return helper_;
}
/// Dereference iterator, returns InputIteratorHelper or OutputIteratorHelper wrapper.
pointer operator->() {
return &helper_;
}
/// Dereference iterator, returns const InputIteratorHelper or OutputIteratorHelper wrapper.
const value_type *operator->() const {
return &helper_;
}
/// Increment to next chunk in list, or to end() iterator.
this_type &operator++() {
++helper_.iter_;
return *this;
}
/// Increment to next chunk in list, or to end() iterator.
this_type operator++(int) {
this_type ret = *this;
++helper_.iter_;
return ret;
}
/// True if iterators point to same chunks.
bool operator==(const this_type &rhs) const {
return (helper_.iter_ == rhs.helper_.iter_);
}
/// True if iterators point to different chunks.
bool operator!=(const this_type &rhs) const {
return (helper_.iter_ != rhs.helper_.iter_);
}
private:
Helper helper_;
};
typedef BufferIterator<InputIteratorHelper> InputBufferIterator;
typedef BufferIterator<OutputIteratorHelper> OutputBufferIterator;
} // namespace detail
} // namespace avro
#endif