#include "stdafx.h"
#include "ptString.h"
#include <assert.h>
#include <stdio.h>
//#define PT_DEBUG
//#ifdef PT_DEBUG
// #include <ptDebugView.h>
//#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef _wcsinc
#define _wcsinc(_pc) ((_pc)+1)
#endif
#ifndef _strinc
#define _strinc(_pc) ((_pc)+1)
#endif
#pragma warning(push)
#pragma warning( disable : 4290 )
CptStringBase::CStrMemBuf* CptStringBase::m_pStrMemBuf = NULL ;
///----------------------------------------------------------------------------------------------------
// 字符串类内存池
CptStringBase::CStrMemBuf::CStrMemBuf()//:m_chEmpty(0)
{
// m_chEmpty = 0 ;
#ifndef USE_STL_MEMORY_FOR_PTSTRING
::memset(m_aMemList,0,sizeof(m_aMemList)) ;
::memset(m_byUnitCount,0,sizeof(m_byUnitCount)) ;
::InitializeCriticalSection(&m_csLock) ;
#endif
::memset(m_EmptyBuf,0,sizeof(m_EmptyBuf)) ;
SStringDesc* pEmptyDesc = (SStringDesc*)m_EmptyBuf ;
pEmptyDesc->nRefs = 1 ;
pEmptyDesc->nUsedSize = 0 ;
pEmptyDesc->nMallocBufSize = 1 ;
#ifdef PT_DEBUG
m_nAllocCounter = 0 ;
m_uAllocBufSize = 0 ;
#endif
}
CptStringBase::CStrMemBuf::~CStrMemBuf()
{
#ifdef PT_DEBUG
Debug_PrintfW(_T("~CStrMemBuf() ")) ;
#endif
#ifndef USE_STL_MEMORY_FOR_PTSTRING
::EnterCriticalSection(&m_csLock) ;
SStringDesc* pResult = NULL ;
for(int i=0; i<sizeof(m_aMemList)/sizeof(void*);++i)
{
while (m_aMemList[i]!=NULL)
{
pResult = reinterpret_cast<SStringDesc*>(m_aMemList[i]) ;
m_aMemList[i] = reinterpret_cast<void*>(*reinterpret_cast<unsigned*>(m_aMemList[i])) ;
--m_byUnitCount[i] ;
if(pResult!=NULL)
{
#ifdef PT_DEBUG
//if(pResult->nMallocBufSize==STRING_SIZE_128)
{
Debug_PrintfW(_T("free() 2 空间 0x%x size=%d ref=%d"),pResult,pResult->nMallocBufSize,pResult->nRefs ) ;
}
//Debug_Printf("free() 1 空间 0x%x",pResult) ;
#endif
::free(pResult) ;
pResult = NULL ;
}
}
}
::LeaveCriticalSection(&m_csLock) ;
::DeleteCriticalSection(&m_csLock) ;
#endif
}
CptStringBase::SStringDesc* CptStringBase::CStrMemBuf::GetEmptyBuffer() const
{
return (SStringDesc*)m_EmptyBuf ;
}
CptStringBase::SStringDesc* CptStringBase::CStrMemBuf::GetBuffer(const UINT uSize)
{
SStringDesc* pResult = NULL ;
#ifdef USE_STL_MEMORY_FOR_PTSTRING
pResult = (SStringDesc*)m_Alloc.allocate(uSize) ;
pResult->nMallocBufSize = uSize ;
#else
int nIndex = -1 ;
UINT uMaxSize = 0 ;
if(uSize<STRING_SIZE_8)
{
nIndex = 0 ;
uMaxSize = STRING_SIZE_8 ;
}
else if(uSize<STRING_SIZE_16)
{
nIndex = 1 ;
uMaxSize = STRING_SIZE_16 ;
}
else if(uSize<STRING_SIZE_32)
{
nIndex = 2 ;
uMaxSize = STRING_SIZE_32 ;
}
else if(uSize<STRING_SIZE_64)
{
nIndex = 3 ;
uMaxSize = STRING_SIZE_64 ;
}
else if(uSize<STRING_SIZE_128)
{
nIndex = 4 ;
uMaxSize = STRING_SIZE_128 ;
}
else if(uSize<STRING_SIZE_256)
{
nIndex = 5 ;
uMaxSize = STRING_SIZE_256 ;
}
else if(uSize<STRING_SIZE_512)
{
nIndex = 6 ;
uMaxSize = STRING_SIZE_512 ;
}
::EnterCriticalSection(&m_csLock) ;
if(nIndex>-1 && nIndex<7)
{
if(m_aMemList[nIndex]!=NULL)
{
pResult = (SStringDesc*)m_aMemList[nIndex] ;
m_aMemList[nIndex] = reinterpret_cast<void*>(*reinterpret_cast<unsigned*>(m_aMemList[nIndex])) ;
--m_byUnitCount[nIndex] ;
#ifdef PT_DEBUG
if(nIndex==4)
{
Debug_PrintfW(_T("摘取了空间 0x%x %d "),pResult,nIndex,pResult->nRefs) ;
}
#endif
}
if(pResult==NULL)
{
switch(nIndex)
{
case 0: pResult = (SStringDesc*)::malloc(STRING_SIZE_8) ; break;
case 1: pResult = (SStringDesc*)::malloc(STRING_SIZE_16) ; break;
case 2: pResult = (SStringDesc*)::malloc(STRING_SIZE_32) ; break;
case 3: pResult = (SStringDesc*)::malloc(STRING_SIZE_64) ; break;
case 4: pResult = (SStringDesc*)::malloc(STRING_SIZE_128) ;break;
case 5: pResult = (SStringDesc*)::malloc(STRING_SIZE_256) ; break;
case 6: pResult = (SStringDesc*)::malloc(STRING_SIZE_512) ; break;
default: break ;
}
}
pResult->nMallocBufSize = uMaxSize ;
#ifdef PT_DEBUG
if(nIndex==4 )
{
Debug_PrintfW(_T("malloc()了空间 0x%x"),pResult) ;
}
#endif
}
if(pResult==NULL)
{
pResult = (SStringDesc*)::malloc(uSize) ;
pResult->nMallocBufSize = uSize ;
}
#ifdef PT_DEBUG
++m_nAllocCounter ;
m_uAllocBufSize += pResult->nMallocBufSize ;
#endif
::LeaveCriticalSection(&m_csLock) ;
#endif
return pResult ;
}
void CptStringBase::CStrMemBuf::ReleaseBuffer(CptStringBase::SStringDesc* pDesc)
{
assert(pDesc!=NULL) ;
#ifdef PT_DEBUG
--m_nAllocCounter ;
m_uAllocBufSize -= pDesc->nMallocBufSize ;
#endif
#ifdef USE_STL_MEMORY_FOR_PTSTRING
m_Alloc.deallocate((char*)pDesc,pDesc->nMallocBufSize) ;
#else
int nIndex = -1 ;
if(pDesc->nMallocBufSize ==STRING_SIZE_16 && m_byUnitCount[0]<MAX_POOL_8)
{
nIndex = 0 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_16 && m_byUnitCount[1]<MAX_POOL_16)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d"),pDesc,STRING_SIZE_16) ;
#endif
nIndex = 1 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_32 && m_byUnitCount[2]<MAX_POOL_32)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d"),pDesc,STRING_SIZE_32) ;
#endif
nIndex = 2 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_64 && m_byUnitCount[3]<MAX_POOL_64)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d"),pDesc,STRING_SIZE_64) ;
#endif
nIndex = 3 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_128 && m_byUnitCount[4]<MAX_POOL_128)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d ref=%d"),pDesc,STRING_SIZE_128,pDesc->nRefs) ;
#endif
nIndex = 4 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_256 && m_byUnitCount[5]<MAX_POOL_256)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d"),pDesc,STRING_SIZE_256) ;
#endif
nIndex = 5 ;
}
else if(pDesc->nMallocBufSize ==STRING_SIZE_512 && m_byUnitCount[6]<MAX_POOL_512)
{
#ifdef PT_DEBUG
//Debug_PrintfW(_T("回收空间 0x%x %d"),pDesc,STRING_SIZE_512) ;
#endif
nIndex = 6 ;
}
::EnterCriticalSection(&m_csLock) ;
if(nIndex>=0)
{
*(reinterpret_cast<unsigned*>(pDesc)) = reinterpret_cast<unsigned>(m_aMemList[nIndex]) ;
m_aMemList[nIndex] = pDesc ;
++m_byUnitCount[nIndex] ;
}
else
{
#ifdef PT_DEBUG
//if(pDesc->nMallocBufSize==STRING_SIZE_128)
{
Debug_PrintfW(_T("free() 1 空间 0x%x size=%d ref=%d"),pDesc,pDesc->nMallocBufSize,pDesc->nRefs) ;
}
#endif
::free(pDesc) ;
}
::LeaveCriticalSection(&m_csLock) ;
#endif
}
//----------------------------------------------------------------------------------------
// CptStringBase
CptStringBase::CptStringBase():m_pchStrData(NULL)
{
}
void CptStringBase::NewMemBufInstance()
{
if(NULL==m_pStrMemBuf)
{
m_pStrMemBuf = new CStrMemBuf() ;
}
}
void CptStringBase::SetEmptyStr()
{
if(m_pchStrData!=NULL && this->GetRefCount()>0)
{
this->DecreaseRef() ;
}
CptStringBase::NewMemBufInstance() ;
m_pchStrData = (StringPointer_t*)(m_pStrMemBuf->GetEmptyBuffer())->GetStringPtr() ;
}
void CptStringBase::AllocBuf(const int nStringSize)
{
CptStringBase::NewMemBufInstance() ;
if(nStringSize>0)
{
SStringDesc* pDesc = (SStringDesc*)(m_pStrMemBuf->GetBuffer(nStringSize+sizeof(SStringDesc)+2)) ;
m_pchStrData = (StringPointer_t*)pDesc->GetStringPtr() ;
::memset(m_pchStrData,0,pDesc->GetStrBufSize()) ;
pDesc->nRefs = 1 ; // 引用 1 次
pDesc->nUsedSize = 0 ; // 长度为0
}
else
{
m_pchStrData = (StringPointer_t*)(m_pStrMemBuf->GetEmptyBuffer())->GetStringPtr() ;
}
//#ifdef PT_DEBUG
// Debug_Printf("申请了空间:0x%x,%d",this->GetStringDesc(),pDesc->nMallocBufSize) ;
//#endif
}
// 释放一个字符串内存空间
void CptStringBase::FreeBuf()
{
if(m_pStrMemBuf!=NULL)
{
m_pStrMemBuf->ReleaseBuffer(this->GetStringDesc()) ;
m_pchStrData = NULL ;
}
}
// 减少引用
inline int CptStringBase::DecreaseRef()
{
_ASSERT(NULL!=m_pchStrData) ;
if(NULL!=m_pStrMemBuf && this->GetStringDesc()!=m_pStrMemBuf->GetEmptyBuffer())
{// 若为非空字符串
int nResult = ::InterlockedDecrement(&(this->GetStringDesc()->nRefs)) ;
#ifdef PT_DEBUG
//if(this->GetStringDesc()->nMallocBufSize==STRING_SIZE_128)
//{
// Debug_PrintfW(_T("减少引用计数:0x%x %d"),this->GetStringDesc(),nResult) ;
//}
#endif
if(nResult==0)
{
this->FreeBuf() ;
}
return nResult;
}
return 1 ;
}
// 增加引用
inline int CptStringBase::IncreaseRef() const
{
_ASSERT(NULL!=m_pchStrData) ;
if(NULL!=m_pStrMemBuf && this->GetStringDesc()!=m_pStrMemBuf->GetEmptyBuffer())
{// 若为非空字符串
int nResult = ::InterlockedIncrement(&(this->GetStringDesc()->nRefs)) ;
return nResult ;
}
return 1 ;
}