📄 strclass.cpp
字号:
/*===========================================================================
*
* Copyright (C) 1997 Hicom Corporation.Ltd. All Rights Reserved.
*
*
* File : strclass.cpp
* Content: String routine
* Program: Lee Jon suk
*
****************************************************************************/
#include "stdafx.h"
//#include <windows.h>
#include <atlbase.h>
//#include <limits.h>
//#include <tchar.h>
#include "stdio.h"
#include "strclass.h"
/////////////////////////////////////////////////////////////////////////////
// static class data, special inlines
// For an empty string, m_???Data will point here
// (note: avoids a lot of NULL pointer tests when we call standard
// C runtime libraries
TCHAR jazzidChNil = '\0';
// for creating empty key strings
const CStrClass jazzidEmptyString;
void CStrClass::Init()
{
m_nDataLength = m_nAllocLength = 0;
m_pchData = (LPTSTR)&jazzidChNil;
}
// declared static
void CStrClass::SafeDelete(LPTSTR lpch)
{
if (lpch != (LPTSTR)&jazzidChNil)
delete[] lpch;
}
//////////////////////////////////////////////////////////////////////////////
// Construction/Destruction
CStrClass::CStrClass()
{
Init();
}
CStrClass::CStrClass(const CStrClass& stringSrc)
{
// if constructing a CStrClass from another CStrClass, we make a copy of the
// original string data to enforce value semantics (i.e. each string
// gets a copy of its own
stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
}
void CStrClass::AllocBuffer(int nLen)
// always allocate one extra character for '\0' termination
// assumes [optimistically] that data length will equal allocation length
{
if (nLen == 0)
{
Init();
}
else
{
m_pchData = new TCHAR[nLen+1]; // may throw an exception
m_pchData[nLen] = '\0';
m_nDataLength = nLen;
m_nAllocLength = nLen;
}
}
void CStrClass::Empty()
{
SafeDelete(m_pchData);
Init();
}
CStrClass::~CStrClass()
// free any attached data
{
SafeDelete(m_pchData);
}
//////////////////////////////////////////////////////////////////////////////
// Helpers for the rest of the implementation
int SafeStrlen(LPCTSTR lpsz)
{
return (lpsz == NULL) ? NULL : _tcslen(lpsz);
}
int CStrClass::GetLength() const
{
return m_nDataLength;
}
void CStrClass::AllocCopy(CStrClass& 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
{
dest.AllocBuffer(nNewLen);
memcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen*sizeof(TCHAR));
}
}
//////////////////////////////////////////////////////////////////////////////
// More sophisticated construction
CStrClass::CStrClass(LPCTSTR lpsz)
{
int nLen;
if ((nLen = SafeStrlen(lpsz)) == 0)
Init();
else
{
AllocBuffer(nLen);
memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
}
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion constructors
#ifdef _UNICODE
CStrClass::CStrClass(LPCSTR lpsz)
{
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
if (nSrcLen == 0)
Init();
else
{
AllocBuffer(nSrcLen);
_mbstowcsz_(m_pchData, lpsz, nSrcLen+1);
}
}
#else //_UNICODE
CStrClass::CStrClass(LPCWSTR lpsz)
{
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
if (nSrcLen == 0)
Init();
else
{
AllocBuffer(nSrcLen);
_wcstombsz_(m_pchData, lpsz, nSrcLen+1);
}
}
#endif //!_UNICODE
//////////////////////////////////////////////////////////////////////////////
// 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 CStrClass&' so that
// assigning it again will cause a copy, eg: s1 = s2 = "hi there".
//
void CStrClass::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
{
// check if it will fit
if (nSrcLen > m_nAllocLength)
{
// it won't fit, allocate another one
Empty();
AllocBuffer(nSrcLen);
}
if (nSrcLen != 0)
memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
m_nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
}
const CStrClass& CStrClass::operator=(const CStrClass& stringSrc)
{
AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
return *this;
}
const CStrClass& CStrClass::operator=(LPCTSTR lpsz)
{
AssignCopy(SafeStrlen(lpsz), lpsz);
return *this;
}
/////////////////////////////////////////////////////////////////////////////
// Special conversion assignment
#ifdef _UNICODE
const CStrClass& CStrClass::operator=(LPCSTR lpsz)
{
int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
// check if it will fit
if (nSrcLen > m_nAllocLength)
{
// it won't fit, allocate another one
Empty();
AllocBuffer(nSrcLen);
}
if (nSrcLen != 0)
_mbstowcsz_(m_pchData, lpsz, nSrcLen+1);
m_nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
return *this;
}
#else //!_UNICODE
const CStrClass& CStrClass::operator=(LPCWSTR lpsz)
{
int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
// check if it will fit
if (nSrcLen > m_nAllocLength)
{
// it won't fit, allocate another one
Empty();
AllocBuffer(nSrcLen);
}
if (nSrcLen != 0)
_wcstombsz_(m_pchData, lpsz, nSrcLen+1);
m_nDataLength = nSrcLen;
m_pchData[nSrcLen] = '\0';
return *this;
}
#endif //!_UNICODE
//////////////////////////////////////////////////////////////////////////////
// concatenation
// NOTE: "operator+" is done as friend functions for simplicity
// There are three variants:
// CStrClass + CStrClass
// and for ? = TCHAR, LPCTSTR
// CStrClass + ?
// ? + CStrClass
void CStrClass::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
int nSrc2Len, LPCTSTR lpszSrc2Data)
{
// -- master concatenation routine
// Concatenate two sources
// -- assume that 'this' is a new CStrClass object
int nNewLen = nSrc1Len + nSrc2Len;
AllocBuffer(nNewLen);
memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
memcpy(&m_pchData[nSrc1Len], lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
}
CStrClass __cdecl operator+(const CStrClass& string1, const CStrClass& string2)
{
CStrClass s;
s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
string2.m_nDataLength, string2.m_pchData);
return s;
}
CStrClass __cdecl operator+(const CStrClass& string, LPCTSTR lpsz)
{
CStrClass s;
s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(lpsz), lpsz);
return s;
}
CStrClass __cdecl operator+(LPCTSTR lpsz, const CStrClass& string)
{
CStrClass s;
s.ConcatCopy(SafeStrlen(lpsz), lpsz, string.m_nDataLength, string.m_pchData);
return s;
}
//////////////////////////////////////////////////////////////////////////////
// concatenate in place
void CStrClass::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
{
// -- the main routine for += operators
// if the buffer is too small, or we have a width mis-match, just
// allocate a new buffer (slow but sure)
if (m_nDataLength + nSrcLen > m_nAllocLength)
{
// we have to grow the buffer, use the Concat in place routine
LPTSTR lpszOldData = m_pchData;
ConcatCopy(m_nDataLength, lpszOldData, nSrcLen, lpszSrcData);
SafeDelete(lpszOldData);
}
else
{
// fast concatenation when buffer big enough
memcpy(&m_pchData[m_nDataLength], lpszSrcData, nSrcLen*sizeof(TCHAR));
m_nDataLength += nSrcLen;
}
m_pchData[m_nDataLength] = '\0';
}
const CStrClass& CStrClass::operator+=(LPCTSTR lpsz)
{
ConcatInPlace(SafeStrlen(lpsz), lpsz);
return *this;
}
const CStrClass& CStrClass::operator+=(TCHAR ch)
{
ConcatInPlace(1, &ch);
return *this;
}
const CStrClass& CStrClass::operator+=(const CStrClass& string)
{
ConcatInPlace(string.m_nDataLength, string.m_pchData);
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// Advanced direct buffer access
LPTSTR CStrClass::GetBuffer(int nMinBufLength)
{
if (nMinBufLength > m_nAllocLength)
{
// we have to grow the buffer
LPTSTR lpszOldData = m_pchData;
int nOldLen = m_nDataLength; // AllocBuffer will tromp it
AllocBuffer(nMinBufLength);
memcpy(m_pchData, lpszOldData, nOldLen*sizeof(TCHAR));
m_nDataLength = nOldLen;
m_pchData[m_nDataLength] = '\0';
SafeDelete(lpszOldData);
}
// return a pointer to the character storage for this string
return m_pchData;
}
void CStrClass::ReleaseBuffer(int nNewLength)
{
if (nNewLength == -1)
nNewLength = lstrlen(m_pchData); // zero terminated
m_nDataLength = nNewLength;
m_pchData[m_nDataLength] = '\0';
}
LPTSTR CStrClass::GetBufferSetLength(int nNewLength)
{
GetBuffer(nNewLength);
m_nDataLength = nNewLength;
m_pchData[m_nDataLength] = '\0';
return m_pchData;
}
void CStrClass::FreeExtra()
{
if (m_nDataLength != m_nAllocLength)
{
LPTSTR lpszOldData = m_pchData;
AllocBuffer(m_nDataLength);
memcpy(m_pchData, lpszOldData, m_nDataLength*sizeof(TCHAR));
SafeDelete(lpszOldData);
}
}
///////////////////////////////////////////////////////////////////////////////
// Commonly used routines (rarely used routines in STREX.CPP)
int CStrClass::Find(TCHAR ch) const
{
// find first single character
LPTSTR lpsz = _tcschr(m_pchData, ch);
// return -1 if not found and index otherwise
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
int CStrClass::FindOneOf(LPCTSTR lpszCharSet) const
{
LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
}
///////////////////////////////////////////////////////////////////////////////
// CStrClass conversion helpers (these use the current system locale)
int _wcstombsz_(char* mbstr, const wchar_t* wcstr, size_t count)
{
if (count == 0 && mbstr != NULL)
return 0;
int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
mbstr, count, NULL, NULL);
if (result > 0)
mbstr[result-1] = 0;
return result;
}
int _mbstowcsz_(wchar_t* wcstr, const char* mbstr, size_t count)
{
if (count == 0 && wcstr != NULL)
return 0;
int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
wcstr, count);
if (result > 0)
wcstr[result-1] = 0;
return result;
}
//////////////////////////////////////////////////////////////////////////////
// More sophisticated construction
CStrClass::CStrClass(TCHAR ch, int nLength)
{
if (nLength < 1)
{
// return empty string if invalid repeat count
Init();
}
else
{
AllocBuffer(nLength);
#ifdef _UNICODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -