#include "stdafx.h"
#include "CvsTrace.h"
#include "CvsString.h"

//
//  Keep a list of 256 byte buffers to recycle.
//

enum {
    cbQuanta    = 256,
    cBOB        = 0xA5,
    cEOB        = 0xA6
};

static char* g_pListOfFreeBuffers;

//
//
//

inline static void CheckBuffer(const char* pBuffer,int cbBuffer = cbQuanta)
{
    ASSERT(pBuffer);
    ASSERT(cBOB == (255&*(pBuffer-1)));
    ASSERT(cEOB == (255&*(pBuffer+cbBuffer)));
}

//
//
//

void CvsString::recycle(char* p,int cb)
{
    CheckBuffer(p,cb);
    --p;
    if (cbQuanta == cb) {
        *(char**)p = g_pListOfFreeBuffers;
        g_pListOfFreeBuffers = p;
        qTRACE(("* recycle %08lx (%d bytes)",(int)p,cb));
    } else {
        delete p;
        qTRACE(("* recycle %08lx (%d bytes) DELETE",(int)p,cb));
    }
}

//
//
//

CvsString::~CvsString()
{
    if (m_sBuffer) {
        char* p = m_sBuffer;
        m_sBuffer = 0;
        recycle(p,m_cbBufferMax);
    }
}

//
//  Upsize the string buffer to at least the given size.
//

void CvsString::resize(int cbNew)
{
    char* sOld      = m_sBuffer;
    int cbOld       = m_cbBufferMax;

    // upsize to 256 byte quanta
    cbNew = (cbNew+255)&~255;

    char* pNew = g_pListOfFreeBuffers;
    if ((cbQuanta == cbNew) && pNew) {
        qTRACE(("* resize %08lx (%d bytes) RECYCLED",(int)pNew,cbNew));
        g_pListOfFreeBuffers = *(char**)pNew;
        *pNew++         = (char)cBOB;
    } else {
        pNew = new char[cbNew+2];
        qTRACE(("* resize %08lx (%d bytes) NEW",(int)pNew,cbNew));
        *pNew++         = (char)cBOB;
        *(pNew+cbNew)   = (char)cEOB;
    }
    memset(pNew,0,cbNew);
    CheckBuffer(pNew,cbNew);

    m_cbBufferMax   = cbNew;
    m_sBuffer       = pNew;

    if (sOld) {
        ASSERT(cbOld <= cbNew);
        memcpy(m_sBuffer,sOld,cbOld);
        recycle(sOld,cbOld);
    }
}
