xflminterface IF_DynaBuf : public XF_RefCount
This class represents a dynamic buffer. XFLAIM does not provide an implementation of this interface. It is up to the application to provide an implementation. Objects of this type are used to return variable length string and binary data to the application. It allows the application to provide an implementation of a "dynamic buffer" that can be resized as needed. When returning data into a IF_DynaBuf object, XFLAIM will call its methods to allocate space that is needed.
Method Summary |
|
void |
truncateData - Truncate the data that is contained in the dynamic buffer to a specified size. |
RCODE |
appendData - Append data to the dynamic buffer. |
RCODE |
allocSpace - Allocate space for data to be appended to the buffer. |
Method Detail |
void truncateData(
FLMUINT uiSize);
When XFLAIM calls this method, it is expected that the dynamic buffer will truncate whatever data it is currently holding down to the specified size (in bytes).
Parameters In:
FLMUINT uiSize Size to truncate the data to - in bytes.
Parameters Out: none
RCODE appendData(
void * pvData,
FLMUINT uiSize);
When XFLAIM calls this method, it is expected that the dynamic buffer will append the passed in data (pvData) to whatever data has already been appended by prior calls to appendData.
Parameters In:
void * pvDat Data that is to be appended to the dynamic buffer. FLMUINT uiSize Size, in bytes, of the data to be appended.
Parameters Out:
RCODE allocSpace(
FLMUINT uiSize,
void ** ppvAlloc);
When XFLAIM calls this method, it is expected that the dynamic buffer will behave as if uiSize bytes of data had been appended to the buffer, even though no data is actually passed into the method to append. The ppvAlloc parameter is a pointer to the place in the dynamic buffer where the appended data would have gone. XFLAIM uses *ppvAlloc after the call as the place where it is to inject data. XFLAIM sometimes calls this method instead of appendData because it knows how big of a buffer it is going to ultimately need, and it is easier to get the buffer and then populate instead of appending data as it goes.
Parameters In:
FLMUINT uiSize The number of bytes to be allocated.
Parameters Out:
void ** ppvAlloc A pointer to the allocated memory is returned here.
BELOW IS AN EXAMPLE OF HOW AN APPLICATION MIGHT WANT TO IMPLEMENT THE IF_DynaBuf INTERFACE.
class App_DynaBuf : public IF_DynaBuf
{
public:
App_DynaBuf(
FLMBYTE * pucBuffer,
// Initial buffer on the stack to use - will reallocate buffer when this is
overflowed.
FLMUINT
uiBufferSize) // Size of buffer on the stack.
{
m_pucBuffer = pucBuffer;
m_uiBufferSize = uiBufferSize;
m_uiOffset = 0;
m_bAllocatedBuffer = FALSE;
}
virtual ~App_DynaBuf()
{
if( m_bAllocatedBuffer)
{
free(
m_pucBuffer);
}
}
void truncateData(
FLMUINT uiSize)
{
if( uiSize < m_uiOffset)
{
m_uiOffset =
uiSize;
}
}
RCODE allocSpace(
FLMUINT uiSize,
void **
ppvPtr)
{
RCODE rc = NE_XFLM_OK;
if( m_uiOffset + uiSize >=
m_uiBufferSize)
{
// Create a buffer big enough for current needs plus another 512 bytes.
if( RC_BAD( rc = resizeBuffer( m_uiOffset + uiSize + 512)))
{
goto Exit;
}
}
// Return pointer to spot where data should be inserted by the caller. Then increment the offset as if the
// data had already been appended. It is the caller's responsibility to
properly fill this space.
*ppvPtr = &m_pucBuffer[ m_uiOffset];
m_uiOffset += uiSize;
Exit:
return( rc);
}
RCODE appendData(
void *
pvData,
FLMUINT uiSize)
{
RCODE rc =
NE_XFLM_OK;
void *
pvTmp;
if( RC_BAD( rc = allocSpace( uiSize,
&pvTmp)))
{
goto Exit;
}
if( uiSize == 1)
{
*((FLMBYTE *)pvTmp)
= *((FLMBYTE *)pvData);
}
else
{
memcpy( pvTmp,
pvData, uiSize);
}
Exit:
return( rc);
}
// Use this method to get pointer to current buffer after returning from XFLAIM call that populated the buffer.
inline FLMBYTE * getBufferPtr( void)
{
return( m_pucBuffer);
}
//
Use this method to get the length of the data in the buffer after returning from
XFLAIM call that populated the buffer.
inline FLMUINT getDataLength( void)
{
return( m_uiOffset);
}
private:
RCODE resizeBuffer(
FLMUINT uiNewSize)
{
RCODE
rc = NE_XFLM_OK;
FLMBYTE * pucOriginalBuf = m_pucBuffer;
if( !m_bAllocatedBuffer)
{
if( uiNewSize
> m_uiBufferSize)
{
if ((m_pucBuffer = (FLMBYTE *)malloc( uiNewSize)) == NULL)
{
m_pucBuffer = pucOriginalBuf;
rc = NE_XFLM_MEM;
goto Exit;
}
m_bAllocatedBuffer = TRUE;
// Must keep all of the data we currently have in the buffer.
if( m_uiOffset)
{
memcpy( m_pucBuffer, pucOriginalBuf, m_uiOffset);
}
}
}
else
{
if ((m_pucBuffer
= (FLMBYTE *)realloc( pucOriginalBuf, uiNewSize)) == NULL)
{
m_pucBuffer = pucOriginalBuf;
rc = NE_XFLM_MEM;
goto Exit;
}
if( uiNewSize < m_uiOffset)
{
m_uiOffset = uiNewSize;
}
}
m_uiBufferSize = uiNewSize;
Exit:
return( rc);
}
//
Private data
FLMBOOL
m_bAllocatedBuffer; // Was m_pucBuffer
allocated? or is it pointing to a stack buffer from constructor?
FLMBYTE * m_pucBuffer;
// Buffer holding data
FLMUINT
m_uiBufferSize;
// Size of the buffer - in bytes
FLMUINT
m_uiOffset;
// Number of bytes in buffer currently populated by XFLAIM - also indicates
place where we should append data when appendData is called.
};