hackedteam/libmelter

View on GitHub
IOBuffer.cc

Summary

Maintainability
Test Coverage
/*
* 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()
{
}