Skip to content

Instantly share code, notes, and snippets.

@gekka
Created April 16, 2024 18:30
Show Gist options
  • Save gekka/363103a8ac8d53f9458ceb9bacad719f to your computer and use it in GitHub Desktop.
Save gekka/363103a8ac8d53f9458ceb9bacad719f to your computer and use it in GitHub Desktop.
Unicodeを書記素で切り出せる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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment