@@ -308,3 +308,202 @@ bool CWordParse::SearchNextWordPosition4KW(
308
308
}
309
309
return false ;
310
310
}
311
+
312
+ // ! wcがasciiなら0-127のまま返す。それ以外は0を返す。
313
+ uchar_t wc_to_c (wchar_t wc)
314
+ {
315
+ #if 0
316
+ //! wcがSJIS1バイト文字ならcharに変換して0~255を返す。SJIS2バイト文字なら0を返す。
317
+ char buf[3]={0,0,0};
318
+ int ret=wctomb(buf,wc);
319
+ if(ret==-1)return 0; //エラー
320
+ if(buf[1]!=0)return 0; //エラー扱い
321
+ return buf[0] <= 0x7F ? buf[0]: 0; //1バイトで表せたので、これを返す 2011.12.17 バッファオーバーランの修正
322
+ #endif
323
+ // 2011.12.15 wctombを使わない版
324
+ if (wc <= 0x7F ){
325
+ return (uchar_t )wc;
326
+ }
327
+ return 0 ;
328
+ }
329
+
330
+ // @@@ 2002.01.24 Start by MIK
331
+ /* !
332
+ 文字列がURLかどうかを検査する。
333
+
334
+ @retval TRUE URLである
335
+ @retval FALSE URLでない
336
+
337
+ @note 関数内に定義したテーブルは必ず static const 宣言にすること(性能に影響します)。
338
+ url_char の値は url_table の配列番号+1 になっています。
339
+ 新しい URL を追加する場合は #define 値を修正してください。
340
+ url_table は頭文字がアルファベット順になるように並べてください。
341
+
342
+ 2007.10.23 kobake UNICODE対応。//$ wchar_t専用のテーブル(または判定ルーチン)を用意したほうが効率は上がるはずです。
343
+ */
344
+ BOOL IsURL (
345
+ const wchar_t * pszLine, // !< [in] 文字列
346
+ int offset, // !< [in] 検査を開始する位置。
347
+ int nLineLen, // !< [in] 文字列の長さ
348
+ int * pnMatchLen // !< [out] URLの長さ。offset からの距離。
349
+ )
350
+ {
351
+ struct _url_table_t {
352
+ wchar_t name[12 ];
353
+ int length;
354
+ bool is_mail;
355
+ };
356
+ static const struct _url_table_t url_table[] = {
357
+ /* アルファベット順 */
358
+ { L" file://" , 7 , false }, /* 1 */
359
+ { L" ftp://" , 6 , false }, /* 2 */
360
+ { L" gopher://" , 9 , false }, /* 3 */
361
+ { L" http://" , 7 , false }, /* 4 */
362
+ { L" https://" , 8 , false }, /* 5 */
363
+ { L" mailto:" , 7 , true }, /* 6 */
364
+ { L" news:" , 5 , false }, /* 7 */
365
+ { L" nntp://" , 7 , false }, /* 8 */
366
+ { L" prospero://" , 11 , false }, /* 9 */
367
+ { L" telnet://" , 9 , false }, /* 10 */
368
+ { L" tp://" , 5 , false }, /* 11 */ // 2004.02.02
369
+ { L" ttp://" , 6 , false }, /* 12 */ // 2004.02.02
370
+ { L" wais://" , 7 , false }, /* 13 */
371
+ { L" {" , 0 , false } /* 14 */ /* '{' is 'z'+1 : terminate */
372
+ };
373
+
374
+ /* テーブルの保守性を高めるための定義 */
375
+ const char urF = 1 ;
376
+ const char urG = 3 ;
377
+ const char urH = 4 ;
378
+ const char urM = 6 ;
379
+ const char urN = 7 ;
380
+ const char urP = 9 ;
381
+ const char urT = 10 ;
382
+ const char urW = 13 ; // 2004.02.02
383
+
384
+ static const char url_char[] = {
385
+ /* +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F */
386
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* +00: */
387
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /* +10: */
388
+ 0 , -1 , 0 , -1 , -1 , -1 , -1 , 0 , 0 , 0 , 0 , -1 , -1 , -1 , -1 , -1 , /* +20: " !"#$%&'()*+,-./" */
389
+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 0 , -1 , 0 , -1 , /* +30: "0123456789:;<=>?" */
390
+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , /* +40: "@ABCDEFGHIJKLMNO" */
391
+ -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 0 , -1 , 0 , 0 , -1 , /* +50: "PQRSTUVWXYZ[\]^_" */
392
+ 0 , -1 , -1 , -1 , -1 , -1 ,urF,urG,urH, -1 , -1 , -1 , -1 ,urM,urN, -1 , /* +60: "`abcdefghijklmno" */
393
+ urP, -1 , -1 , -1 ,urT, -1 , -1 ,urW, -1 , -1 , -1 , 0 , 0 , 0 , -1 , 0 , /* +70: "pqrstuvwxyz{|}~ " */
394
+ /* あと128バイト犠牲にすればif文を2箇所削除できる */
395
+ /* 0 : not url char
396
+ * -1 : url char
397
+ * other: url head char --> url_table array number + 1
398
+ */
399
+ };
400
+
401
+ const wchar_t * const begin = pszLine + offset;
402
+ const wchar_t * const end = pszLine + nLineLen;
403
+ const struct _url_table_t *urlp;
404
+ int i;
405
+
406
+ if ( wc_to_c (*begin)==0 ) return FALSE ; /* 2バイト文字 */
407
+ if ( 0 < url_char[wc_to_c (*begin)] ){ /* URL開始文字 */
408
+ for (urlp = &url_table[url_char[wc_to_c (*begin)]-1 ]; urlp->name [0 ] == wc_to_c (*begin); urlp++){ /* URLテーブルを探索 */
409
+ if ( (urlp->length <= end - begin) && (auto_memcmp (urlp->name , begin, urlp->length ) == 0 ) ){ /* URLヘッダは一致した */
410
+ if ( urlp->is_mail ){ /* メール専用の解析へ */
411
+ if ( IsMailAddress (begin, urlp->length , end - begin - urlp->length , pnMatchLen) ){
412
+ *pnMatchLen = *pnMatchLen + urlp->length ;
413
+ return TRUE ;
414
+ }
415
+ return FALSE ;
416
+ }
417
+ for (i = urlp->length ; i < end - begin; i++){ /* 通常の解析へ */
418
+ if ( wc_to_c (begin[i])==0 || (!(url_char[wc_to_c (begin[i])])) ) break ; /* 終端に達した */
419
+ }
420
+ if ( i == urlp->length ) return FALSE ; /* URLヘッダだけ */
421
+ *pnMatchLen = i;
422
+ return TRUE ;
423
+ }
424
+ }
425
+ }
426
+ return IsMailAddress (pszLine, offset, nLineLen, pnMatchLen);
427
+ }
428
+
429
+ /* 現在位置がメールアドレスならば、NULL以外と、その長さを返す
430
+ @date 2016.04.27 記号類を許可
431
+ */
432
+ BOOL IsMailAddress ( const wchar_t * pszBuf, int offset, int nBufLen, int * pnAddressLenfth )
433
+ {
434
+ struct {
435
+ bool operator ()(const wchar_t ch)
436
+ {
437
+ return 0x21 <= ch && ch <= 0x7E && NULL == wcschr (L" \" (),:;<>@[\\ ]" , ch);
438
+ }
439
+ } IsValidChar;
440
+
441
+ /*
442
+ 直前の文字を利用した境界判定
443
+ */
444
+ if (0 < offset && IsValidChar (pszBuf[offset-1 ])) {
445
+ return FALSE ;
446
+ }
447
+
448
+ pszBuf += offset;
449
+ nBufLen -= offset;
450
+ offset = 0 ;
451
+
452
+ int j;
453
+ int nDotCount;
454
+ int nBgn;
455
+
456
+
457
+ j = 0 ;
458
+ if (pszBuf[j] != L' .' && IsValidChar (pszBuf[j])){
459
+ j++;
460
+ }else {
461
+ return FALSE ;
462
+ }
463
+ while ( j < nBufLen - 2 && IsValidChar (pszBuf[j]) ){
464
+ j++;
465
+ }
466
+ if ( j == 0 || j >= nBufLen - 2 ){
467
+ return FALSE ;
468
+ }
469
+ if ( L' @' != pszBuf[j] ){
470
+ return FALSE ;
471
+ }
472
+ // nAtPos = j;
473
+ j++;
474
+ nDotCount = 0 ;
475
+ // nAlphaCount = 0;
476
+
477
+
478
+ for (;;) {
479
+ nBgn = j;
480
+ while ( j < nBufLen &&
481
+ (
482
+ (pszBuf[j] >= L' a' && pszBuf[j] <= L' z' )
483
+ || (pszBuf[j] >= L' A' && pszBuf[j] <= L' Z' )
484
+ || (pszBuf[j] >= L' 0' && pszBuf[j] <= L' 9' )
485
+ || (pszBuf[j] == L' -' )
486
+ || (pszBuf[j] == L' _' )
487
+ )
488
+ ){
489
+ j++;
490
+ }
491
+ if ( 0 == j - nBgn ){
492
+ return FALSE ;
493
+ }
494
+ if ( L' .' != pszBuf[j] ){
495
+ if ( 0 == nDotCount ){
496
+ return FALSE ;
497
+ }else {
498
+ break ;
499
+ }
500
+ }else {
501
+ nDotCount++;
502
+ j++;
503
+ }
504
+ }
505
+ if ( NULL != pnAddressLenfth ){
506
+ *pnAddressLenfth = j;
507
+ }
508
+ return TRUE ;
509
+ }
0 commit comments