>1
CStringという文字列を#defineで別名に置換することで本来のCStringを置き換えてみました。
// pch.h: プリコンパイル済みヘッダー ファイルです。
// 次のファイルは、その後のビルドのビルド パフォーマンスを向上させるため 1 回だけコンパイルされます。
// コード補完や多くのコード参照機能などの IntelliSense パフォーマンスにも影響します。
// ただし、ここに一覧表示されているファイルは、ビルド間でいずれかが更新されると、すべてが再コンパイルされます。
// 頻繁に更新するファイルをここに追加しないでください。追加すると、パフォーマンス上の利点がなくなります。
#ifndef PCH_H
#define PCH_H
#define CString CStringDef
// プリコンパイルするヘッダーをここに追加します
#include "framework.h"
#include <icu.h>
#pragma comment(lib, "icu.lib")
#undef CString
template< typename BaseType, class StringTraits >
class CStringExT : public ATL::CStringT<BaseType, StringTraits> {
using CStringT::CStringT;
private:
int32_t GraphemeLength(UBreakIterator* pIterator)
{
LPCWSTR p = GetBuffer();
int32_t count = 0;
int32_t temp;
while (UBRK_DONE != (temp = ubrk_next(pIterator))) {
count++;
if (p[temp] == L'\0')
{//末尾を超えて列挙してしまうバグがある?
//break;
}
}
return count;
};
public:
int32_t GraphemeLength()
{
CStringDef d;
d.GetBuffer();
LPCWSTR p = GetBuffer();
UErrorCode errcode;
UBreakIterator* pIterator = ubrk_open(UBRK_CHARACTER, ULOC_JAPAN, (UChar const*)p, -1, &errcode);
uint32_t count = GraphemeLength(pIterator);
return count;
};
CStringExT GraphemeMid(int32_t iFirst, int32_t nCount)
{
LPCWSTR p = GetBuffer();
UErrorCode errcode;
UBreakIterator* pIterator = ubrk_open(UBRK_CHARACTER, ULOC_JAPAN, (UChar const*)p, -1, &errcode);
ubrk_first(pIterator);
int32_t start = skipGrapheme(pIterator, iFirst, p);
int32_t end = skipGrapheme(pIterator, nCount, p);
ubrk_close(pIterator);
return CStringT::Mid(start, end - start);
};
CStringExT GraphemeMid(int32_t iFirst)
{
LPCWSTR p = GetBuffer();
UErrorCode errcode;
UBreakIterator* pIterator = ubrk_open(UBRK_CHARACTER, ULOC_JAPAN, (UChar const*)p, -1, &errcode);
ubrk_first(pIterator);
int32_t start = skipGrapheme(pIterator, iFirst, p);
ubrk_close(pIterator);
return CStringT::Mid(start);
};
CStringExT GraphemeLeft(int32_t count) {
LPCWSTR p = GetBuffer();
UErrorCode errcode;
UBreakIterator* pIterator = ubrk_open(UBRK_CHARACTER, ULOC_JAPAN, (UChar const*)p, -1, &errcode);
int32_t start = ubrk_first(pIterator);
int32_t end = skipGrapheme(pIterator, count, p);
ubrk_close(pIterator);
return CStringT::Mid(start, end - start);
};
CStringExT GraphemeRight(int32_t count)
{
CString ret;
LPCWSTR p = GetBuffer();
UErrorCode errcode;
UBreakIterator* pIterator = ubrk_open(UBRK_CHARACTER, ULOC_JAPAN, (UChar const*)p, -1, &errcode);
int index = ubrk_first(pIterator);
int len = GraphemeLength(pIterator);
int skipCount = len - count;
if (skipCount <= 0)
{
ret = CStringExT(p);
}
else
{
ubrk_first(pIterator);
int start = skipGrapheme(pIterator, skipCount, p);
ret = CStringExT(p + start);
}
ubrk_close(pIterator);
return ret;
};
#if OVERRIDE_CSTRING_DEFAULT_METHODS
CStringExT Mid(int iFirst)
{
//return CStringDef::Mid(iFirst);
return GraphemeMid(iFirst);
}
CStringExT Mid(int iFirst, int nCount)
{
//return CStringDef::Mid(iFirst,nCount);
return GraphemeMid(iFirst, nCount);
}
CStringExT Left(int nCount)
{
//return CStringDef::Left(nCount);
return GraphemeLeft(nCount);
}
CStringExT Right(int nCount)
{
//return CStringDef::Right(nCount);
return GraphemeRight(nCount);
}
#endif
private:
static int32_t skipGrapheme(UBreakIterator* pIterator, int32_t count, LPCWSTR const p = nullptr)
{
uint32_t index = ubrk_current(pIterator);
while (count--)
{
int32_t end = ubrk_next(pIterator);
if (end == UBRK_DONE)
{
break;
}
index = end;
if (p != nullptr && p[end] == L'\0')
{//末尾を超えて列挙してしまうバグがある?
break;
}
}
return index;
};
};
typedef CStringExT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
#endif //PCH_H
Mid,Left,Rightをどのような意図で使用しているのかは、実際に使用しているコードに依存するので、既存の関数を単純な置換で置き換えるのは止めた方がいいと思います。
たとえばデータベースで固定長や文字数上限のあるの文字型の列に格納する文字列を用意する事を意図して使用している箇所で、書記素区切りの文字列を設定しようとしたら意図せず大きな文字列になってエラーになる可能性があります。