#include <stdarg.h>
#include "cstring.h"
#include "fixalloc.h"
using namespace std;
#if defined(_WIN32)
#define vsnprintf _vsnprintf
#endif
static inline LPSTR NextChar(LPCSTR p);
static char* _cstrchr(const char* p, char ch);
static char* _cstrrchr(const char* p, char ch);
static char* _cstrrev(char* pStr);
static char* _cstrstr(const char* pStr, const char* pCharSet);
// Globals
// For an empty string, m_pchData will point here
// (note: avoids special case of checking for NULL m_pchData)
// empty string data (and locked)
static int rgInitData[] = { -1, 0, 0, 0 };
static CStringData* StrDataNil = (CStringData*)&rgInitData;
static LPCSTR StrPchNil = (LPCSTR)(((byte*)&rgInitData) + sizeof(CStringData));
#define ROUND(x,y) (((x)+(y-1))&~(y-1))
#define ROUND4(x) ROUND(x, 4)
static CFixedAlloc StrAlloc64(ROUND4(65*sizeof(char)+sizeof(CStringData)));
static CFixedAlloc StrAlloc128(ROUND4(129*sizeof(char)+sizeof(CStringData)));
static CFixedAlloc StrAlloc256(ROUND4(257*sizeof(char)+sizeof(CStringData)));
static CFixedAlloc StrAlloc512(ROUND4(513*sizeof(char)+sizeof(CStringData)));
#if defined(__GNUC__)
ptSpinLock CString::lockrefs;
#endif
const CString& CString::_GetEmptyString()
{
return *(CString*)&StrPchNil;
}
CString::CString(const CString& stringSrc)
{
assert(stringSrc.GetData()->nRefs != 0);
if (stringSrc.GetData()->nRefs >= 0)
{
assert(stringSrc.GetData() != StrDataNil);
m_pchData = stringSrc.m_pchData;
safe_inc((int*)&GetData()->nRefs);
}
else
{
Init();
*this = stringSrc.m_pchData;
}
}
bool CString::AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
assert(nLen >= 0);
assert(nLen <= INT_MAX - 1); // max size (enough room for 1 extra)
if (nLen == 0)
{
Init();
}
else
{
CStringData* pData = NULL;
if (nLen <= 64)
{
pData = (CStringData*)StrAlloc64.Alloc();
pData->nAllocLength = 64;
}
else if (nLen <= 128)
{
pData = (CStringData*)StrAlloc128.Alloc();
pData->nAllocLength = 128;
}
else if (nLen <= 256)
{
pData = (CStringData*)StrAlloc256.Alloc();
pData->nAllocLength = 256;
}
else if (nLen <= 512)
{
pData = (CStringData*)StrAlloc512.Alloc();
pData->nAllocLength = 512;
}
else
{
pData = (CStringData*)new byte[sizeof(CStringData) + (nLen + 1) * sizeof(char)];
pData->nAllocLength = nLen;
}
pData->nRefs = 1;
pData->data()[nLen] = '\0';
pData->nDataLength = nLen;
m_pchData = pData->data();
}
return true;
}
void CString::Release()
{
if (GetData() != StrDataNil)
{
assert(GetData()->nRefs != 0);
if (safe_dec((int*)&GetData()->nRefs) <= 0)
FreeData(GetData());
Init();
}
}
void CString::Release(CStringData* pData)
{
if (pData != StrDataNil)
{
assert(pData->nRefs != 0);
if (safe_dec((int*)&pData->nRefs) <= 0)
FreeData(pData);
}
}
void CString::Empty()
{
if (GetData()->nDataLength == 0)
return;
if (GetData()->nRefs >= 0)
Release();
else
*this = "";
assert(GetData()->nDataLength == 0);
assert(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
}
void CString::CopyBeforeWrite()
{
if (GetData()->nRefs > 1)
{
CStringData* pData = GetData();
Release();
if(AllocBuffer(pData->nDataLength))
memcpy(m_pchData, pData->data(), (pData->nDataLength + 1) * sizeof(char));
}
assert(GetData()->nRefs <= 1);
}
bool CString::AllocBeforeWrite(int nLen)
{
bool bRet = true;
if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
{
Release();
bRet = AllocBuffer(nLen);
}
assert(GetData()->nRefs <= 1);
return bRet;
}
const CString& CString::Append(int n)
{
char szBuffer[10];
sprintf(szBuffer,"%d",n);
ConcatInPlace(SafeStrlen(szBuffer), szBuffer);
return *this;
}
CString::~CString()
// free any attached data
{
if (GetData() != StrDataNil)
{
if (safe_dec((int*)&GetData()->nRefs) <= 0)
FreeData(GetData());
}
}
void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
int nExtraLen) const
{
// will clone the data attached to this string
// allocating 'nExtraLen' characters
// Places results in uninitialized string 'dest'
// Will copy the part or all of original data to start of new string
int nNewLen = nCopyLen + nExtraLen;
if (nNewLen == 0)
{
dest.Init();
}
else
{
if(dest.AllocBuffer(nNewLen))
memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen * sizeof(char));
}
}
CString::CString(LPCSTR lpsz)
{
Init();
int nLen = SafeStrlen(lpsz);
if (nLen != 0)
{
if(AllocBuffer(nLen))
memcpy(m_pchData, lpsz, nLen * sizeof(char));
}
}
// Assignment operators
// All assign a new value to the string
// (a) first see if the buffer is big enough
// (b) if enough room, copy on top of old buffer, set size and type
// (c) otherwise free old string data, and create a new one
//
// All routines return the new string (but as a 'const CString&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//
void CString::AssignCopy(int nSrcLen, LPCSTR lpszSrcData)
{
if(AllocBeforeWrite(nSrcLen))
{
memcpy(m_pchData, lpszSrcData, nSrcLen * sizeof(char));
GetData()->nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}
}
const CString& CString::operator=(const CString& stringSrc)
{
if (m_pchData != stringSrc.m_pchData)
{
if ((GetData()->nRefs < 0 && GetData() != StrDataNil) || stringSrc.GetData()->nRefs < 0)
{
// actual copy necessary since one of the strings is locked
AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
}
else
{
// can just copy references around
Release();
assert(stringSrc.GetData() != StrDataNil);
m_pchData = stringSrc.m_pchData;
safe_inc((int*)&GetData()->nRefs);
}
}
return *this;
}
const CString& CString::operator=(LPCSTR lpsz)
{
assert(lpsz != NULL);
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
// Concatenation
// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// CString + CString
// and for ? = char, LPCSTR
// CString + ?
// ? + CString
bool CString::ConcatCopy(int nSrc1Len, LPCSTR lpszSrc1Data,
int nSrc2Len, LPCSTR lpszSrc2Data)
{
// -- master concatenation routine
// Concatenate two sources
// -- assume that 'this' is a new CString object
bool bRet = true;
int nNewLen = nSrc1Len + nSrc2Len;
if (nNewLen != 0)
{
bRet = AllocBuffer(nNewLen);
if (bRet)
{
memcpy(m_pchData, lpszSrc1Data, nSrc1Len * sizeof(char));
memcpy(m_pchData + nSrc1Len, lpszSrc2Data, nSrc2Len * sizeof(char));
}
}
return bRet;
}
CString operator+(const CString& string1, const CString& string2)
{
CString s;
s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData);
return s;
}
CString operator+(const CString& string, LPCSTR lpsz)
{
assert(lpsz != NULL);
CString s;
s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz);
return s;
}
CString operator+(LPCSTR lpsz, const CString& string)
{
assert(lpsz != NULL);
CString s;
s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetDat
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
cstring_linux.rar (9个子文件)
cstring_linux
fixalloc.h 1KB
fixalloc.cpp 2KB
cstring.cpp 27KB
main.cpp 305B
ptspinlock.h 2KB
ptmutexlock.h 3KB
plex.h 1KB
makefile 303B
cstring.h 11KB
共 9 条
- 1
hlyces
- 粉丝: 14
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
前往页