Title
最終更新日:2000/03/02
目次

MFCライク文字列操作クラス

MFCでは、CString文字列クラスがあって便利だが、 いざMFCを使わないアプリケーションとなると CStringをまねたクラスを作ってしまおうとうお話。

(※要注意! サンプルにつき、バグあり)

CTmstr

//  tmstr.h: クラス定義

///////////////////////////////////////////////////////////////
//  CTmstrクラス
//  Copyright(c) 1999, by T-maru
//
//  1999/10/29: CSriingライクな文字列操作クラス
//              2バイト文字判定を付加する。
//  1999/10/31: Left など CString汎用をサポート
//
///////////////////////////////////////////////////////////////
// インクルード
#include "windows.h"
#include <mbstring.h>

//#define _MFCDEBUG
////////////////////////////////////////////////////////////////
//
// CTmstrクラス定義
//
class CTmstr
{
public:
	// コンストラクター/デストラクター
	CTmstr(){
#ifdef _MFCDEBUG
		TRACE("Tmstr()\n");
#endif
		init();
	};
	CTmstr(const char *data){
#ifdef _MFCDEBUG
		TRACE("Tmstr(const char *data)\n");
#endif
		init();
		Add(data);
	}
	CTmstr(char *data, int len){
#ifdef _MFCDEBUG
		TRACE("Tmstr(char *data,int len)\n");
#endif
		init();
		Add(data, len);
	};
	CTmstr(const CTmstr & str){
#ifdef _MFCDEBUG
		TRACE("Tmstr(const CTmstr & str), nRefs=%d\n",str.nRefs);
#endif
		if( str.nRefs > 0){
			m_pchData = str.m_pchData;
			m_nSize = str.m_nSize;
			m_nCur  = str.m_nCur;
			nRefs = str.nRefs-1;
		}
		else{
			init();
			Add(str.m_pchData,str.m_nCur);
		}
	}
	~CTmstr(){
#ifdef _MFCDEBUG
		TRACE("~CTmstr() ref=%d\n", nRefs);
#endif
		if(nRefs<=0) Free();
	};
	
	// メモリー開放
	void Free(){
#ifdef _MFCDEBUG
		TRACE("Free()\n");
#endif
		if (m_pchData ) delete []m_pchData;
		init();
	};

	// バッファー操作
	char* Detach(){	
		char *p = m_pchData;
		init();
		return p;
	};
	char *GetBuffer(int size=-1);
	void ReleaseBuffer();

	// オペレーター
	const CTmstr & operator  =( LPCSTR pszstr );
	const CTmstr & operator  =( TCHAR ch );
	const CTmstr & operator  =( CTmstr& str );
	const CTmstr & operator +=( LPCSTR pszstr );
	const CTmstr & operator +=( TCHAR ch );
	const CTmstr& operator  +=( const CTmstr& string );
	operator LPCTSTR() const;	// as a C string
	char operator[](int nIndex) const // same as GetAt
	{ return GetAt(nIndex); };

	friend CTmstr __stdcall operator+(const CTmstr& string1,const CTmstr& string2);
	friend CTmstr __stdcall operator+(const CTmstr& string, char ch);
	friend CTmstr __stdcall operator+(TCHAR ch, const CTmstr& string);
	friend CTmstr __stdcall operator+(const CTmstr& string, LPCTSTR lpsz);
	friend CTmstr __stdcall operator+(LPCTSTR lpsz, const CTmstr& string);

	// 標準関数
	int GetLength(){return m_nCur;};
	void Empty(){
		m_nCur=0;
		if( m_pchData ) m_pchData[0] = 0;
	};
	BOOL IsEmpty(){return (m_nCur<1); }
	void Add(char ch);
	void Add(char *data,int len);
	void Add(const char *data);
	void Add(CTmstr & tmstr);
	char GetAt(int index) const{
		if( index <0 || index >= m_nCur )
			return NULL;
		return m_pchData[index];
	};
	void SetAt(int index, char ch){
		if( index<0 || index >= m_nCur)
			return;
		m_pchData[index] = ch ;
	};

	// 漢字補助
	static BOOL IsKanji(int c);
	static char *jstrchr( char* lpszSrc, const unsigned char uchSerchCode);
	static char *jstrrchr( char* lpszSrc, const unsigned char uchSerchCode);
	static char *jstrstr( const char *string1, const char *string2 );

	// 文字列操作
	void Reverse();
	void Trim();
	void TrimLeft();
	void TrimRight();
	int Find(char c);
	int Find(LPCSTR serch);
	int ReverseFind(char c);
	int ReverseFind(LPCSTR serch);
	void Replace(LPCSTR search, LPCSTR replace);
	void Upper();
	void Lower();
	int Compare( LPCTSTR lpsz ) const;
	int CompareNoCase( LPCTSTR lpsz ) const;
	
	CTmstr Left(int nCount) const;
	CTmstr Right(int nCount) const;
	CTmstr Mid(int nFirst) const;
	CTmstr Mid(int nFirst, int nCount) const;
	CTmstr SpanIncluding(LPCTSTR lpszCharSet) const;
	CTmstr SpanExcluding(LPCTSTR lpszCharSet) const;

protected:
	// 初期化
	void init(){m_pchData=NULL;m_nSize=m_nCur=nRefs=0;};
	void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data);

private:
	// メンバー変数
	char *m_pchData;	// buffer pointer
	int m_nSize;	// buffer size
	int m_nCur;		// current length
	int nRefs;      // reference count
};

////////////////////////////////////////////////////////////////
//
// CTmstrメンバー関数定義
//

////////////////////////////////////////////////////////////////
// オペレーター

// Compare helpers ( ==, !=, <, >, <= ,>= )
inline bool __stdcall operator==(const CTmstr& s1, const CTmstr& s2)
	{ return s1.Compare(s2) == 0; }
inline bool __stdcall operator==(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) == 0; }
inline bool __stdcall operator==(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) == 0; }

inline bool __stdcall operator!=(const CTmstr& s1, const CTmstr& s2)
	{ return s1.Compare(s2) != 0; }
inline bool __stdcall operator!=(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) != 0; }
inline bool __stdcall operator!=(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) != 0; }

inline bool __stdcall operator<(const CTmstr& s1, const CTmstr& s2)
	{ return s1.Compare(s2) < 0; }
inline bool __stdcall operator<(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) < 0; }
inline bool __stdcall operator<(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) < 0; }

inline bool __stdcall operator>(const CTmstr& s1, const CTmstr& s2)
	{ return s1.Compare(s2) > 0; }
inline bool __stdcall operator>(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) > 0; }
inline bool __stdcall operator>(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) > 0; }

inline bool __stdcall operator<=(const CTmstr& s1, const CTmstr& s2)
	{ return s1.Compare(s2) <= 0; }
inline bool __stdcall operator<=(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) <= 0; }
inline bool __stdcall operator<=(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) <= 0; }

inline bool __stdcall operator>=(const CTmstr& s1, const CTmstr& s2)
	{ return s2.Compare(s2) >= 0; }
inline bool __stdcall operator>=(const CTmstr& s1, LPCTSTR s2)
	{ return s1.Compare(s2) >= 0; }
inline bool __stdcall operator>=(LPCTSTR s1, const CTmstr& s2)
	{ return s2.Compare(s1) >= 0; }

// 連結ヘルパー
void CTmstr::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data)
{
	int nNewLen = nSrc1Len + nSrc2Len;
	if (nNewLen != 0)
	{
//		AllocBuffer(nNewLen);
//		memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(char));
//		memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(char));
		Add((char*)lpszSrc1Data, nSrc1Len);
		Add((char*)lpszSrc2Data, nSrc2Len);
	}
}

// operator +
CTmstr __stdcall operator+(const CTmstr& string1,const CTmstr& string2)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator+(CTmstr,CTmstr)\n");
#endif
	CTmstr s;
	s.ConcatCopy(string1.m_nCur, string1.m_pchData,
		string2.m_nCur, string2.m_pchData);
	return s;
}
CTmstr __stdcall operator+(const CTmstr& string, char ch)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator+(CTmstr,char)\n");
#endif
	CTmstr s;
	s.ConcatCopy(string.m_nCur, string.m_pchData, 1, &ch);
	return s;
}
CTmstr __stdcall operator+(char ch, const CTmstr& string)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator+(char,CTmstr)\n");
#endif
	CTmstr s;
	s.ConcatCopy(1, &ch, string.m_nCur, string.m_pchData);
	return s;
}
CTmstr __stdcall operator+(const CTmstr& string, LPCTSTR lpsz)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator+(CTmstr,LPCTSTR)\n");
#endif
	CTmstr s;
	s.ConcatCopy(string.m_nCur, string.m_pchData,
		lstrlen(lpsz), lpsz);
	return s;
}
CTmstr __stdcall operator+(LPCTSTR lpsz, const CTmstr& string)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator+(LPCTSTR,CTmstr)\n");
#endif
	CTmstr s;
	s.ConcatCopy(lstrlen(lpsz), lpsz, string.m_nCur,
		string.m_pchData);
	return s;
}

// operator =
const CTmstr &  CTmstr::operator=(LPCSTR pszstr)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator=(LPCSTR pszstr)\n");
	ASSERT(pszstr == NULL || AfxIsValidString(pszstr, FALSE));
#endif
	Empty();
	Add(pszstr);
	return *this;
}
const CTmstr &  CTmstr::operator=(TCHAR ch)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator=(TCHAR ch)\n");
#endif
	Empty();
	Add(&ch, 1);
	return *this;
}
const CTmstr &  CTmstr::operator=( CTmstr& str )
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator=( CTmstr& str )\n");
#endif
	if(m_pchData != str.m_pchData)
	{
		Empty();
		Add(str);
	}
	return *this;
}

// operator +=
const CTmstr& CTmstr::operator +=( LPCSTR pszstr )
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator +=( LPCSTR pszstr )\n");
#endif
	Add(pszstr);
	return *this;
}
const CTmstr& CTmstr::operator +=( TCHAR ch )
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator +=( TCHAR ch )\n");
#endif
	Add(ch);
	return *this;
}
const CTmstr& CTmstr::operator +=( const CTmstr& string )
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator +=( Tmstr & string )\n");
#endif
	Add(string.m_pchData, string.m_nCur);
	return *this;
}

// operator LPCTSTR()
CTmstr::operator LPCTSTR() const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::operator LPCTSTR()\n");
#endif
	return (LPCTSTR)this->m_pchData;
}

////////////////////////////////////////////////////////////////
// バッファー操作
char* CTmstr::GetBuffer(int size/*=-1*/)
{
	if ( size > 0 ){
		if( size > m_nSize ){
			TCHAR *tp = new TCHAR[size + 2048];
			if (tp == NULL) {
				if (m_pchData)
					delete [] m_pchData;
				throw "CStr out of space";
			}
			if (m_pchData) {
				memcpy(tp,m_pchData,m_nCur);
				delete [] m_pchData;
			}
			m_pchData = tp;
			m_nSize = size + 2048;
			m_pchData[m_nSize-1] = 0;
		}
	}
	return m_pchData;
}
void CTmstr::ReleaseBuffer()
{
	if(m_pchData){
		if(m_nSize>0){
			m_pchData[m_nSize-1] = '\0';
			m_nCur = lstrlen(m_pchData);
			return;
		}
	}
	Free();
}
////////////////////////////////////////////////////////////////
// 標準操作
void CTmstr::Add(char ch)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Add(char ch)\n");
#endif
	Add(&ch, 1);
}
void CTmstr::Add(const char *data)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Add(const char *data)\n");
#endif
	int len = -1;
	len = lstrlen(data);
	if( len <=0 ){
		return;
	}

	if (m_nSize <= m_nCur + len ) {
		char *tp = new char[m_nSize + len + 2048];
		if (tp == NULL) {
			if (m_pchData)
				delete [] m_pchData;
			throw "CTmstr out of space";
		}
		if (m_pchData) {
			memcpy(tp,m_pchData,m_nCur);
			delete [] m_pchData;
		}
		m_pchData = tp;
		m_nSize = m_nSize + len + 2048;
		m_pchData[m_nSize-1] = 0;
	}
	memcpy(m_pchData+m_nCur,data,len);
	m_nCur += len;
	m_pchData[m_nCur] = 0;
}
void CTmstr::Add(char *data,int len)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Add(char*data ,int len)\n");
#endif
	if (len <= 0){
		return;
	}

	if (m_nSize <= m_nCur + len ) {
		char *tp = new char[m_nSize + len + 2048];
		if (tp == NULL) {
			if (m_pchData)
				delete [] m_pchData;
			throw "CTmstr out of space";
		}
		if (m_pchData) {
			memcpy(tp,m_pchData,m_nCur);
			delete [] m_pchData;
		}
		m_pchData = tp;
		m_nSize = m_nSize + len + 2048;
		m_pchData[m_nSize-1] = 0;
	}
	memcpy(m_pchData+m_nCur,data,len);
	m_nCur += len;
	m_pchData[m_nCur] = 0;
}
void CTmstr::Add(CTmstr& tmstr)
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Add(CTmstr& tmstr)\n");
#endif
	if(tmstr.nRefs<=0){
		long len = tmstr.GetLength();
		TCHAR *p = tmstr.GetBuffer();
		Add( p, len);
	}
	else{
		Free();
		m_pchData = tmstr.m_pchData;
		m_nSize = tmstr.m_nSize;
		m_nCur  = tmstr.m_nCur;
		tmstr.nRefs--;
		tmstr.m_pchData = NULL;
	}
}

/////////////////////////////////////////////////////////////
// 漢字補助
BOOL CTmstr::IsKanji(int c) {

    static
    unsigned char sjis_table[256] =
    {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 0x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 1x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 2x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 3x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 4x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 5x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 6x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* 7x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 8x */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* 9x */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* Ax */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* Bx */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* Cx */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* Dx */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     /* Ex */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,     /* Fx */
    };
    return sjis_table[c & 0xff];
}
char* CTmstr::jstrchr( char* lpszSrc, const unsigned char uchSerchCode)
{
	return  (char*)_mbschr((const unsigned char*)lpszSrc, uchSerchCode);
/*
	// この方が高速
    char* lpszResult = NULL;
    while( *lpszSrc )
	{
		// 2バイト文字列は無視する
		if( IsKanji( (unsigned char)*lpszSrc ) )
		{
			lpszSrc += 2;
			continue;
		}
		if( (unsigned char)*lpszSrc == uchSerchCode ){
			lpszResult = lpszSrc;
			break;
		}
		lpszSrc++;
	}
	return lpszResult;
*/
}
char* CTmstr::jstrrchr( char* lpszSrc, const unsigned char uchSerchCode)
{
	return  (char*)_mbsrchr((const unsigned char*)lpszSrc, uchSerchCode);
/*
    char* lpszResult = NULL;
    while( *lpszSrc )
	{
		// 2バイト文字列は無視する
		if( IsKanji( (unsigned char)*lpszSrc ) )
		{
			lpszSrc += 2;
			continue;
		}
		if( (unsigned char)*lpszSrc == uchSerchCode )
			lpszResult = lpszSrc;
		lpszSrc++;
	}
	return lpszResult;
*/
}
char * CTmstr::jstrstr( const char *string1, const char *string2 )
{
	return (char*)_mbsstr((const unsigned char*)string1,
		(const unsigned char*)string2);

/*
	// この方が高速
    char* lpszResult = NULL;
	int i = 0;
	const unsigned char *s1 = (const unsigned char*)string1;
	const unsigned char *s2 = s1 + i;
	char *tmp = NULL;
	while(1){
		tmp = strstr(string1+i, string2);
		if( tmp == NULL )
			break;

		i = (tmp - string1);
		s2 = s1 + i;
		if(_ismbstrail(s1, s2)<0 )
		{
			i++;
			continue;
		}

		lpszResult = tmp;
		break;
	}
	return lpszResult;
*/
}

/////////////////////////////////////////////////////////
// 文字列操作

// バッファー文字列を逆転する
// 2バイト文字対応!
void CTmstr::Reverse(){
	if( IsEmpty() ) return;

	int len = m_nCur;
	char* p = m_pchData;
	char* tmp = new char[len+1];
	tmp[len--] = '\0';

	while(*p){
		if( IsKanji(*p)){
			*(tmp+(len-1)) = *p++;
			*(tmp+(len)) = *p++;
			len -= 2;
		}
		else *(tmp+(len--)) = *p++;
	}
	lstrcpy(m_pchData, tmp);
	delete []tmp;
}

// バッファー前後の改行・半角空白・タブを削除する
void CTmstr::Trim()
{
	if(IsEmpty()) return;

	TrimLeft();
	TrimRight();
}
void CTmstr::TrimLeft()
{
	if(IsEmpty()) return;

	char *p = m_pchData;
	int i=0;
	while(*p == ' ' || *p == '\t' || *p == '\r'|| *p == '\n' )
	{ i++; p++; }
	
	if( i> 0 ){
		m_nCur -= i;
		memmove(m_pchData, p, m_nCur);
		m_pchData[m_nCur] = '\0';
	}
}
void CTmstr::TrimRight()
{
	if(IsEmpty()) return;

	char *p = m_pchData+(m_nCur-1);
	int i=0;
	while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
	{ i++; p--; }

	if( i> 0 ){
		m_nCur -= i;
		m_pchData[m_nCur] = '\0';
	}
}

// バッファー内検索
// 戻り値:  0 以上の場合 0 から始める文字インデックス
//         -1 の場合     見つからなかった
// 2バイト文字対応!
int CTmstr::Find(char c)
{
	if(IsEmpty()) return -1;

	char *p = jstrchr(m_pchData, c);
	if (p != NULL)
		return (int)(p - m_pchData);
	return -1;
}
int CTmstr::Find(LPCSTR serch)
{
	if(IsEmpty()) return -1;

	char *p = jstrstr(m_pchData, serch);
	if (p != NULL)
		return (int)(p - m_pchData);
	return -1;
}
int CTmstr::ReverseFind(char c)
{
	if(IsEmpty()) return -1;
	
	char *p = jstrrchr(m_pchData, c);
	if (p != NULL)
		return (int)(p - m_pchData);
	return -1;
}
int CTmstr::ReverseFind(LPCSTR serch)
{
	if(IsEmpty()) return -1;

	char *p = m_pchData;
	char *tmp = NULL;
	char *fd = NULL;
	while(1){
		tmp = jstrstr( p, serch );
		if( tmp != NULL ){
			fd = tmp;
		}
		else break;
		p = tmp +1 ;
	}

	// 最後に見つかった位置を返す。
	if( fd != NULL)
		return (int)(fd - m_pchData);
	return -1;
}

// バッファー内の検索文字列を 指定文字列に置き換える。
void CTmstr::Replace(LPCSTR search, LPCSTR replace)
{
	if(IsEmpty()) return;
	
	CTmstr buffer;
	int slen = lstrlen(search);
	int rlen = lstrlen(replace);
	
	if(slen <= 0 )
		return;

	char *p = m_pchData;
	char *tmp = NULL;

	while(*p){
		tmp = jstrstr(p, search);
		if (tmp == NULL)
		{
			buffer.Add((LPCSTR)p);
			break;
		}
		buffer.Add(p, (tmp - p) );
		buffer.Add(replace);
		p = tmp + slen;
	}

	if( buffer.GetLength() >0 ){
		Empty();
		Add(buffer.GetBuffer(), buffer.GetLength());
	}
}

// バッファーを大文字・小文字に変換
void CTmstr::Upper()
{
	if(IsEmpty()) return;
	CharUpper(m_pchData);
}
void CTmstr::Lower()
{
	if(IsEmpty()) return;
	CharLower(m_pchData);
}

// バッファー文字列比較
// 戻り値: 0    同じ
//         負数 比較対照より小さい
//         整数 比較対象より大きい
int CTmstr::Compare( LPCTSTR lpsz ) const
{
	//if(IsEmpty()) return -1;
	return _mbscmp((const unsigned char*)m_pchData, (const unsigned char*)lpsz);
}
int CTmstr::CompareNoCase( LPCTSTR lpsz ) const 
{
	//if(IsEmpty()) return -1;
	// 大文字小文字区別なし
	return _mbsicmp((const unsigned char*)m_pchData, (const unsigned char*)lpsz);
}

/////////////////////////////////////////////
// 文字列抽出
CTmstr CTmstr::Left(int nCount)const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Left(%d)\n", nCount);
#endif
	if (nCount < 0)
		nCount = 0;
	else if (nCount > m_nCur)
		nCount = m_nCur;

	CTmstr dest;
	dest.Add(m_pchData, nCount);
	dest.nRefs++;
	return dest;
}
CTmstr CTmstr::Right(int nCount)const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Right(%d)\n", nCount);
#endif
	if (nCount < 0)
		nCount = 0;
	else if (nCount > m_nCur)
		nCount = m_nCur;

	CTmstr dest;
	dest.Add(m_pchData+(m_nCur-nCount), nCount);
	dest.nRefs++;
	return dest;
}
CTmstr CTmstr::Mid(int nFirst)const
{
	return Mid(nFirst,m_nCur-nFirst);
}
CTmstr CTmstr::Mid(int nFirst, int nCount)const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::Mid(nFirst=%d, nCount=%d)\n", nFirst, nCount);
#endif
	// out-of-bounds requests return sensible things
	if (nFirst < 0)	nFirst = 0;
	if (nCount < 0)	nCount = 0;

	if (nFirst + nCount > m_nCur)
		nCount = m_nCur - nFirst;
	if (nFirst > m_nCur)
		nCount = 0;

	CTmstr dest;
	dest.Add(m_pchData+nFirst, nCount);
	dest.nRefs++;
	return dest;
}
// strspn equivalent
CTmstr CTmstr::SpanIncluding(LPCTSTR lpszCharSet) const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::SpanIncluding()\n");
#endif
	//ASSERT(AfxIsValidString(lpszCharSet, FALSE));
	return Left(_mbsspn(
		(const unsigned char*)m_pchData, (const unsigned char*)lpszCharSet));
}

// strcspn equivalent
CTmstr CTmstr::SpanExcluding(LPCTSTR lpszCharSet) const
{
#ifdef _MFCDEBUG
	TRACE("CTmstr::SpanExcluding()\n");
#endif
	//ASSERT(AfxIsValidString(lpszCharSet, FALSE));
	return Left( _mbscspn(
		(const unsigned char*)m_pchData, (const unsigned char*)lpszCharSet));
}

#ifdef _MFCDEBUG
	#undef _MFCDEBUG
#endif


CopyRight(c)1999-2000, by T-maru
ご連絡はメールにて

GeoCities Japan