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

truncateData

    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

[Back to Top]


appendData

    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:

[Back to Top]


allocSpace

    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.

   

[Back to Top]


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.
};