blob: 14288bee428e3f77185340f81f3938f5db966dcf [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed 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
*
* http://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 VIRTUAL_BUFFER_H_INCLUDED
#define VIRTUAL_BUFFER_H_INCLUDED
#ifndef OSCL_TYPES_H_INCLUDED
#include "oscl_types.h"
#endif
#ifndef OSCL_VECTOR_H_INCLUDED
#include "oscl_vector.h"
#endif
#ifndef OSCL_REFCOUNTER_MEMFRAG_H_INCLUDED
#include "oscl_refcounter_memfrag.h"
#endif
#ifndef OSCL_ASSERT_H_INCLUDED
#include "oscl_assert.h"
#endif
template<class TBufferAccess>
class VirtualBuffer
{
public:
VirtualBuffer();
VirtualBuffer(const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& buffers);
virtual ~VirtualBuffer();
// copy constructor
// VirtualBuffer<TBufferAccess>(const VirtualBuffer<TBufferAccess>& original);
VirtualBuffer<TBufferAccess>(const VirtualBuffer<TBufferAccess>& original)
{
pCurrFrag = NULL;
pCurrFragPos = NULL;
currIndex = 0;
for (uint i = 0; i < original.vFragments.size(); i++)
{
appendBuffer(original.vFragments[i]);
}
currIndex = original.currIndex;
pCurrFrag = &vFragments[currIndex];
pCurrFragPos = original.pCurrFragPos;
}
// buffer operations
void appendBuffer(const OsclRefCounterMemFrag& frag);
void reset();
// operators
TBufferAccess& operator*(); // indirection
VirtualBuffer& operator=(const VirtualBuffer&); // assignment
operator TBufferAccess*()
{
return pCurrFragPos;
}; // cast
VirtualBuffer& operator++(); // prefix increment
VirtualBuffer operator++(int); // postfix increment
VirtualBuffer& operator+=(const int increment); // addition
// create a new virtual buffer from the current position
// for the specified range
void createSubBuffer(uint length, VirtualBuffer<TBufferAccess>& subRange);
// create a new virtual buffer from the current position
void createSubBuffer(VirtualBuffer<TBufferAccess>& subRange);
// copy fragments into vector
void copy(Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& vOutFrags);
// fragment vector accessor
const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& fragments()
{
return vFragments;
}
// return the virtual length
uint length();
protected:
void advance();
void setCurrPointer()
{
pCurrFragPos = reinterpret_cast<TBufferAccess*>(pCurrFrag->getMemFragPtr());
}
Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator> vFragments;
OsclRefCounterMemFrag* pCurrFrag;
int currIndex;
TBufferAccess* pCurrFragPos;
};
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>::VirtualBuffer()
{
pCurrFrag = NULL;
pCurrFragPos = NULL;
currIndex = 0;
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>::VirtualBuffer(const Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& buffers)
{
OSCL_ASSERT(buffers.size() > 0);
pCurrFrag = NULL;
pCurrFragPos = NULL;
currIndex = 0;
for (uint i = 0; i < buffers.size(); i++)
{
appendBuffer(buffers[i]);
}
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>::~VirtualBuffer()
{
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator=(const VirtualBuffer & original)
{
if (&original != this)
{
vFragments.clear();
for (uint i = 0; i < original.vFragments.size(); i++)
{
appendBuffer(original.vFragments[i]);
}
currIndex = original.currIndex;
pCurrFrag = &vFragments[currIndex];
pCurrFragPos = original.pCurrFragPos;
}
return *this;
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::appendBuffer(const OsclRefCounterMemFrag& frag)
{
vFragments.push_back(frag);
if (pCurrFrag == NULL)
{
currIndex = 0;
pCurrFrag = &vFragments[currIndex];
setCurrPointer();
}
else
{
pCurrFrag = &vFragments[currIndex];
}
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::reset()
{
pCurrFrag = NULL;
currIndex = 0;
vFragments.clear();
}
template<class TBufferAccess>
TBufferAccess& VirtualBuffer<TBufferAccess>::operator*()
{
OSCL_ASSERT(pCurrFragPos != NULL);
return *pCurrFragPos;
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator++()
{
advance();
return *this;
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess> VirtualBuffer<TBufferAccess>::operator++(int)
{
VirtualBuffer<TBufferAccess> temp(*this);
advance();
return temp;
}
template<class TBufferAccess>
VirtualBuffer<TBufferAccess>& VirtualBuffer<TBufferAccess>::operator+=(const int increment)
{
for (int i = 0; i < increment; i++)
{
advance();
}
return *this;
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::createSubBuffer(uint length,
VirtualBuffer<TBufferAccess>& subRange)
{
subRange.reset();
uint bytesNeeded = length;
TBufferAccess* position = pCurrFragPos;
OsclRefCounterMemFrag* pFragment = pCurrFrag;
while (1 && pCurrFrag != NULL)
{
OsclRefCounterMemFrag frag(*pFragment);
frag.getMemFrag().ptr = position;
uint32 bytesInFrag = ((TBufferAccess*)pFragment->getMemFragPtr() + pFragment->getMemFragSize()) - position;
frag.getMemFrag().len = bytesInFrag > bytesNeeded ? bytesNeeded : bytesInFrag;
subRange.appendBuffer(frag);
bytesNeeded -= frag.getMemFrag().len;
if (bytesNeeded == 0)
{
break;
}
pFragment++;
if (pFragment != vFragments.end())
{
// move position to the front of the next buffer
position = reinterpret_cast<TBufferAccess*>(pFragment->getMemFragPtr());
}
else
{
// ran out of data
break;
}
}
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::copy(Oscl_Vector<OsclRefCounterMemFrag, OsclMemAllocator>& vOutFrags)
{
for (uint i = 0; i < vFragments.size(); i++)
{
vOutFrags.push_back(vFragments[i]);
}
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::createSubBuffer(VirtualBuffer<TBufferAccess>& subRange)
{
subRange.reset();
TBufferAccess* position = pCurrFragPos;
OsclRefCounterMemFrag* pFragment = pCurrFrag;
if (pCurrFrag == NULL)
{
//no fragment left
return;
}
while (1)
{
OsclRefCounterMemFrag frag(*pFragment);
frag.getMemFrag().ptr = position;
frag.getMemFrag().len = ((TBufferAccess*)pFragment->getMemFragPtr() + pFragment->getMemFragSize()) - position;
subRange.appendBuffer(frag);
pFragment++;
if (pFragment != vFragments.end())
{
// move position to the front of the next buffer
position = reinterpret_cast<TBufferAccess*>(pFragment->getMemFragPtr());
}
else
{
break;
}
}
}
template<class TBufferAccess>
void VirtualBuffer<TBufferAccess>::advance()
{
// advance our intra buffer pointer
++pCurrFragPos;
// check if we've exhausted the current buffer
// NOTE: The check assumes that the len field in the
// OsclMemoryFragments is a byte count.
if ((TBufferAccess*)(pCurrFragPos) == (TBufferAccess*)pCurrFrag->getMemFragPtr() +
pCurrFrag->getMemFragSize())
{
// advance to the next fragment
pCurrFrag++;
if (pCurrFrag == vFragments.end())
{
// no fragments left
pCurrFrag = NULL;
pCurrFragPos = NULL;
currIndex = 0;
return;
}
currIndex++;
setCurrPointer();
}
}
template<class TBufferAccess>
uint VirtualBuffer<TBufferAccess>::length()
{
uint len = 0;
for (uint i = 0; i < vFragments.size(); i++)
{
len += vFragments[i].getMemFrag().len;
}
return len;
}
#endif // VIRTUAL_BUFFER_H_INCLUDED