Skip to content

Commit

Permalink
Merge pull request sakura-editor#421 from berryzplus/feature/speed_up…
Browse files Browse the repository at this point in the history
…_mailaddress_check

メールアドレスの色替え判定を高速化すると同時にRFCに準拠させる
  • Loading branch information
beru committed Sep 14, 2018
2 parents 5ae8797 + 9e3d55b commit c5cd5d1
Show file tree
Hide file tree
Showing 11 changed files with 731 additions and 204 deletions.
193 changes: 0 additions & 193 deletions sakura_core/parse/CWordParse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,196 +317,3 @@ bool CWordParse::SearchNextWordPosition4KW(
}
return false;
}


//! wcがasciiなら0-127のまま返す。それ以外は0を返す。
uchar_t wc_to_c(wchar_t wc)
{
#if 0
//! wcがSJIS1バイト文字ならcharに変換して0~255を返す。SJIS2バイト文字なら0を返す。
char buf[3]={0,0,0};
int ret=wctomb(buf,wc);
if(ret==-1)return 0; //エラー
if(buf[1]!=0)return 0; //エラー扱い
return buf[0] <= 0x7F ? buf[0]: 0; //1バイトで表せたので、これを返す 2011.12.17 バッファオーバーランの修正
#endif
// 2011.12.15 wctombを使わない版
if(wc <= 0x7F){
return (uchar_t)wc;
}
return 0;
}

//@@@ 2002.01.24 Start by MIK
/*!
文字列がURLかどうかを検査する。
@retval TRUE URLである
@retval FALSE URLでない
@note 関数内に定義したテーブルは必ず static const 宣言にすること(性能に影響します)。
url_char の値は url_table の配列番号+1 になっています。
新しい URL を追加する場合は #define 値を修正してください。
url_table は頭文字がアルファベット順になるように並べてください。
2007.10.23 kobake UNICODE対応。//$ wchar_t専用のテーブル(または判定ルーチン)を用意したほうが効率は上がるはずです。
*/
BOOL IsURL(
const wchar_t* pszLine, //!< [in] 文字列
int nLineLen, //!< [in] 文字列の長さ
int* pnMatchLen //!< [out] URLの長さ
)
{
struct _url_table_t {
wchar_t name[12];
int length;
bool is_mail;
};
static const struct _url_table_t url_table[] = {
/* アルファベット順 */
{ L"file://", 7, false }, /* 1 */
{ L"ftp://", 6, false }, /* 2 */
{ L"gopher://", 9, false }, /* 3 */
{ L"http://", 7, false }, /* 4 */
{ L"https://", 8, false }, /* 5 */
{ L"mailto:", 7, true }, /* 6 */
{ L"news:", 5, false }, /* 7 */
{ L"nntp://", 7, false }, /* 8 */
{ L"prospero://", 11, false }, /* 9 */
{ L"telnet://", 9, false }, /* 10 */
{ L"tp://", 5, false }, /* 11 */ //2004.02.02
{ L"ttp://", 6, false }, /* 12 */ //2004.02.02
{ L"wais://", 7, false }, /* 13 */
{ L"{", 0, false } /* 14 */ /* '{' is 'z'+1 : terminate */
};

/* テーブルの保守性を高めるための定義 */
const char urF = 1;
const char urG = 3;
const char urH = 4;
const char urM = 6;
const char urN = 7;
const char urP = 9;
const char urT = 10;
const char urW = 13; //2004.02.02

static const char url_char[] = {
/* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +00: */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* +10: */
0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, -1, /* +20: " !"#$%&'()*+,-./" */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, /* +30: "0123456789:;<=>?" */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* +40: "@ABCDEFGHIJKLMNO" */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, /* +50: "PQRSTUVWXYZ[\]^_" */
0, -1, -1, -1, -1, -1,urF,urG,urH, -1, -1, -1, -1,urM,urN, -1, /* +60: "`abcdefghijklmno" */
urP, -1, -1, -1,urT, -1, -1,urW, -1, -1, -1, 0, 0, 0, -1, 0, /* +70: "pqrstuvwxyz{|}~ " */
/* あと128バイト犠牲にすればif文を2箇所削除できる */
/* 0 : not url char
* -1 : url char
* other: url head char --> url_table array number + 1
*/
};

const wchar_t *p = pszLine;
const struct _url_table_t *urlp;
int i;

if( wc_to_c(*p)==0 ) return FALSE; /* 2バイト文字 */
if( 0 < url_char[wc_to_c(*p)] ){ /* URL開始文字 */
for(urlp = &url_table[url_char[wc_to_c(*p)]-1]; urlp->name[0] == wc_to_c(*p); urlp++){ /* URLテーブルを探索 */
if( (urlp->length <= nLineLen) && (auto_memcmp(urlp->name, pszLine, urlp->length) == 0) ){ /* URLヘッダは一致した */
p += urlp->length; /* URLヘッダ分をスキップする */
if( urlp->is_mail ){ /* メール専用の解析へ */
if( IsMailAddress(p, nLineLen - urlp->length, pnMatchLen) ){
*pnMatchLen = *pnMatchLen + urlp->length;
return TRUE;
}
return FALSE;
}
for(i = urlp->length; i < nLineLen; i++, p++){ /* 通常の解析へ */
if( wc_to_c(*p)==0 || (!(url_char[wc_to_c(*p)])) ) break; /* 終端に達した */
}
if( i == urlp->length ) return FALSE; /* URLヘッダだけ */
*pnMatchLen = i;
return TRUE;
}
}
}
return IsMailAddress(pszLine, nLineLen, pnMatchLen);
}

/* 現在位置がメールアドレスならば、NULL以外と、その長さを返す
@date 2016.04.27 記号類を許可
*/
BOOL IsMailAddress( const wchar_t* pszBuf, int nBufLen, int* pnAddressLenfth )
{
int j;
int nDotCount;
int nBgn;


j = 0;
if( (pszBuf[j] >= L'a' && pszBuf[j] <= L'z')
|| (pszBuf[j] >= L'A' && pszBuf[j] <= L'Z')
|| (pszBuf[j] >= L'0' && pszBuf[j] <= L'9')
|| NULL != wcschr(L"!#$%&'*+-/=?^_`{|}~", pszBuf[j])
){
j++;
}else{
return FALSE;
}
while( j < nBufLen - 2 &&
(
(pszBuf[j] >= L'a' && pszBuf[j] <= L'z')
|| (pszBuf[j] >= L'A' && pszBuf[j] <= L'Z')
|| (pszBuf[j] >= L'0' && pszBuf[j] <= L'9')
|| (pszBuf[j] == L'.')
|| NULL != wcschr(L"!#$%&'*+-/=?^_`{|}~", pszBuf[j])
)
){
j++;
}
if( j == 0 || j >= nBufLen - 2 ){
return FALSE;
}
if( L'@' != pszBuf[j] ){
return FALSE;
}
// nAtPos = j;
j++;
nDotCount = 0;
// nAlphaCount = 0;


for (;;) {
nBgn = j;
while( j < nBufLen &&
(
(pszBuf[j] >= L'a' && pszBuf[j] <= L'z')
|| (pszBuf[j] >= L'A' && pszBuf[j] <= L'Z')
|| (pszBuf[j] >= L'0' && pszBuf[j] <= L'9')
|| (pszBuf[j] == L'-')
|| (pszBuf[j] == L'_')
)
){
j++;
}
if( 0 == j - nBgn ){
return FALSE;
}
if( L'.' != pszBuf[j] ){
if( 0 == nDotCount ){
return FALSE;
}else{
break;
}
}else{
nDotCount++;
j++;
}
}
if( NULL != pnAddressLenfth ){
*pnAddressLenfth = j;
}
return TRUE;
}
4 changes: 0 additions & 4 deletions sakura_core/parse/CWordParse.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,6 @@ class CWordParse{
static bool _match_charlist( const WCHAR c, const WCHAR *pszList );
};

BOOL IsURL( const wchar_t*, int, int* );/* 指定アドレスがURLの先頭ならばTRUEとその長さを返す */
BOOL IsMailAddress( const wchar_t*, int, int* ); /* 現在位置がメールアドレスならば、NULL以外と、その長さを返す */



// ACHAR 版
inline bool CWordParse::_match_charlist( const ACHAR c, const ACHAR *pszList )
Expand Down
Loading

0 comments on commit c5cd5d1

Please sign in to comment.