DequeAsStream.h

// DequeAsStream.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2004

#pragma once
#ifndef Ceda_cxUtils_DequeAsStream_H
#define Ceda_cxUtils_DequeAsStream_H

#include "cxUtils.h"
#include "StreamInterfaces.h"
#include <deque>
#include <algorithm>

namespace ceda
{

///////////////////////////////////////////////////////////////////////////////////////////////////
// Adapter to make a deque<octet_t> look like an IOutputStream

class DequeToOutputStreamAdapter : public IOutputStream
{
public:
    DequeToOutputStreamAdapter(std::deque<octet_t>& d) : m_deque(d) {}
    
    // Implementation of IOutputStream
    virtual void WriteStream(const void* buffer, ssize_t numBytes)
    {
        const octet_t* p = reinterpret_cast<const octet_t*>(buffer);
        const octet_t* p_end = p + numBytes;
        while(p != p_end) m_deque.push_back(*p++);
    }
    virtual void FlushStream() {}

private:
    std::deque<octet_t>& m_deque;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// Adapter to make a deque<octet_t> look like an IOutputStream at the back, and an IInputStream at
// the front.

class DequeAsBidirectionalStream : public IOutputStream, public IInputStream
{
public:
    DequeAsBidirectionalStream(std::deque<octet_t>& d) : m_deque(d) {}
    
    // Implementation of IOutputStream
    virtual void WriteStream(const void* buffer, ssize_t numBytes)
    {
        const octet_t* p = reinterpret_cast<const octet_t*>(buffer);
        const octet_t* p_end = p + numBytes;
        while(p != p_end) m_deque.push_back(*p++);
    }
    virtual void FlushStream() {}
    
    // Implementation of IInputStream
    virtual ssize_t ReadStream(void* buffer, ssize_t numBytesRequested)
    {
        cxAssert(0 <= numBytesRequested);
        cxAssert(numBytesRequested == 0 || buffer != nullptr);
        
        ssize_t size = m_deque.size();
        ssize_t n = std::min(size, numBytesRequested);
        if (n > 0)
        {
            cxAssert(buffer);
            octet_t* p = (octet_t*) buffer;
            std::deque<octet_t>::const_iterator b = m_deque.begin();
            std::deque<octet_t>::const_iterator e = b + n;
            for (std::deque<octet_t>::const_iterator i = b ; i != e ; ++i)
            {
                *p++ = *i;
            }
            m_deque.erase(b,e);
        }
        return n;
    }

private:
    std::deque<octet_t>& m_deque;
};

} // namespace ceda

#endif // include guard