IOBuffer.cc
/*
* IOBuffer.cpp
*
* Created on: Sep 28, 2010
* Author: daniele
*/
#include <cassert>
#include <iostream>
#include <string>
#include <utility>
#include <boost/foreach.hpp>
#include "BufferObserver.h"
#include "IOBuffer.h"
#include "Chunk.h"
std::size_t IOBuffer::append( Chunk &a )
{
_push_back(a);
_notify();
return a.size();
}
std::size_t IOBuffer::prepend( Chunk &a )
{
_push_front(a);
_offset -= a.size();
return a.size();
}
void IOBuffer::_push_back( Chunk &a )
{
_data.insert( _data.end(), a.ptr(), a.ptr() + a.size() );
}
void IOBuffer::_push_front( Chunk &a )
{
_data.insert( _data.begin(), a.ptr(), a.ptr() + a.size() );
}
Chunk IOBuffer::pop( std::size_t size )
{
if(!size)
return 0;
if ( available(_offset) < size )
return Chunk( _offset );
Chunk c = Chunk( &_data[0], BufferDescriptor(_offset, size) );
_data.erase( _data.begin(), _data.begin() + size );
_offset += size;
return c;
}
Chunk IOBuffer::range( BufferDescriptor descriptor )
{
if ( ! this->descriptor().contains( descriptor ) )
return Chunk( "", BufferDescriptor( descriptor.offset(), 0));
std::size_t index = descriptor.offset() - _offset;
return Chunk(&_data[index], BufferDescriptor(descriptor.offset(), descriptor.size()) );
}
Chunk IOBuffer::range( std::size_t start_offset, std::size_t size )
{
return range( BufferDescriptor(start_offset, size) );
}
std::size_t IOBuffer::flush( std::size_t to_offset )
{
assert( to_offset >= _offset );
std::size_t size = to_offset - _offset;
// if we don't have enough data for flushing, flush what's available
if (size > this->size())
size = this->size();
_data.erase( _data.begin(), _data.begin() + size);
_offset += size;
return size;
}
std::size_t IOBuffer::available(std::size_t start_offset)
{
// if the starting offset falls outside our buffer, return 0
if (start_offset < _offset || start_offset > _offset + this->size())
return 0;
else
return (_offset + _data.size()) - start_offset;
}
void IOBuffer::register_observer( ::prototype::BufferObserver& observer )
{
//std::cout << "[IOBuffer] registering observer for source buffer." << std::endl;
_observers.push_front( &observer );
}
void IOBuffer::remove_observer( ::prototype::BufferObserver& observer )
{
_observers.remove( &observer );
}
void IOBuffer::_notify()
{
BOOST_FOREACH( ::prototype::BufferObserver* observer, _observers )
observer->update();
}
IOBuffer::IOBuffer()
: _offset(0)
{
}
IOBuffer::~IOBuffer()
{
}