Advertisement
mahorori

findpattern

May 11th, 2016
406
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.51 KB | None | 0 0
  1. // .h
  2. #pragma once
  3.  
  4. #include <vector>
  5.  
  6. typedef struct _SEARCH_CONTEXT
  7. {
  8.     std::vector<USHORT> vusXPattern;
  9.     INT nLength;
  10.     INT iBC[0x100];
  11. } SEARCH_CONTEXT, far *LPSEARCH_CONTEXT, near *PSEARCH_CONTEXT, SRCH_CTX, far *LPSRCH_CTX, near *PSRCH_CTX;
  12.  
  13. #define NB_ERR  0xFF
  14. #define NB_WC   0xCC
  15. #define NB_WC_1 0x100
  16. #define NB_WC_2 0x200
  17.  
  18. LPVOID FindPatternA(__in_bcount(nSize) LPCVOID lpcv, __in INT nSize, __in LPCSTR lpPattern);
  19. LPVOID FindPatternW(__in_bcount(nSize) LPCVOID lpcv, __in INT nSize, __in LPCWSTR lpPattern);
  20.  
  21. #ifdef _UNICODE
  22. #define FindPattern FindPatternW
  23. #else
  24. #define FindPattern FindPatternA
  25. #endif
  26.  
  27. // .cpp
  28. #include "stdafx.h"
  29.  
  30. #include "findpattern.h"
  31. #include <memory>
  32.  
  33. static const BYTE s_cbNibble[0x100] =
  34. {
  35.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x08
  36.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x10
  37.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x18
  38.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x20
  39.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x28
  40.     NB_ERR, NB_ERR, NB_WC, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x30
  41.     0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, // 0x38
  42.     0x8, 0x9, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_WC, // 0x40
  43.     NB_ERR, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, NB_ERR, // 0x48
  44.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x50
  45.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x58
  46.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x60
  47.     NB_ERR, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, NB_ERR, // 0x68
  48.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x70
  49.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x78
  50.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x80
  51.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x88
  52.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x90
  53.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0x98
  54.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xA0
  55.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xA8
  56.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xB0
  57.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xB8
  58.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xC0
  59.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xC8
  60.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xD0
  61.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xD8
  62.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xE0
  63.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xE8
  64.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xF0
  65.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, // 0xF8
  66.     NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR, NB_ERR  // 0xFF
  67. };
  68.  
  69. BOOL GenerateXPattern(__inout LPSRCH_CTX lpCTX, __in LPCWSTR lpPattern)
  70. {
  71.     USHORT  usCurrent;
  72.     BYTE    bN1, bN2;
  73.     WCHAR   *pwszTemp;
  74.  
  75.     lpCTX->vusXPattern.clear();
  76.     lpCTX->nLength = 0;
  77.  
  78.     pwszTemp = (WCHAR *)lpPattern;
  79.     do
  80.     {
  81.         // skip white-spaces
  82.         while (isspace(*pwszTemp) != 0)
  83.             pwszTemp++;
  84.  
  85.         // grab first nibble [X?]
  86.         bN1 = s_cbNibble[*pwszTemp++];
  87.  
  88.         if (isspace(*pwszTemp) != 0)
  89.         {
  90.             // single
  91.             if (bN1 == NB_ERR)
  92.                 return FALSE;
  93.  
  94.             // generate & store x-pattern
  95.             usCurrent = bN1 == NB_WC ? (NB_WC_1 | NB_WC_2) : bN1;
  96.         }
  97.         else
  98.         {
  99.             // double
  100.             // grab second nibble [?X]
  101.             bN2 = s_cbNibble[*pwszTemp++];
  102.  
  103.             if (bN1 == NB_ERR || bN2 == NB_ERR)
  104.                 return FALSE;
  105.  
  106.             // generate & store x-pattern
  107.             usCurrent = bN1 == NB_WC ? NB_WC_1 : bN1 << 4;
  108.             usCurrent |= bN2 == NB_WC ? NB_WC_2 : bN2;
  109.         }
  110.  
  111.         lpCTX->nLength++;
  112.         lpCTX->vusXPattern.push_back(usCurrent);
  113.     } while (*pwszTemp != L'\0');
  114.  
  115.     return TRUE;
  116. }
  117.  
  118. __inline BOOL XEqual(__in WORD w1, __in WORD w2)
  119. {
  120.     switch ((w1 >> 8) | (w2 >> 8))
  121.     {
  122.         case 0:     return w1 == w2;
  123.         case 1:     return (w1 & 0x0F) == (w2 & 0x0F);
  124.         case 2:     return (w1 & 0xF0) == (w2 & 0xF0);
  125.         case 3:     return TRUE;
  126.         default:    return FALSE;
  127.     }
  128. }
  129.  
  130. VOID CalculateBC(__inout LPSRCH_CTX lpCTX)
  131. {
  132.     INT i, n, cLength;
  133.  
  134.     // パターンに無い文字のずらし幅
  135.     for (i = 0; i < 0x100; i++)
  136.         lpCTX->iBC[i] = lpCTX->nLength + 1;
  137.  
  138.     // パターンに含まれる文字のずらし幅
  139.     for (i = 0; i < lpCTX->nLength; i++)
  140.     {
  141.         cLength = lpCTX->nLength - i;
  142.  
  143.         switch (lpCTX->vusXPattern[i] >> 8)
  144.         {
  145.             case 1: // NB_WC_1 (?X)
  146.                 for (n = 0; n < 0x10; n++)
  147.                     lpCTX->iBC[(n << 4) | (lpCTX->vusXPattern[i] & 0x0F)] = cLength;
  148.                 break;
  149.  
  150.             case 2: // NB_WC_2 (X?)
  151.                 for (n = 0; n < 0x10; n++)
  152.                     lpCTX->iBC[n | (lpCTX->vusXPattern[i] & 0xF0)] = cLength;
  153.                 break;
  154.  
  155.             case 3: // NB_WC_1 | NB_WC_2
  156.                 for (n = 0; n < 0x100; n++)
  157.                     lpCTX->iBC[n] = cLength;
  158.                 break;
  159.  
  160.             default:
  161.                 lpCTX->iBC[lpCTX->vusXPattern[i]] = cLength;
  162.         }
  163.     }
  164. }
  165.  
  166. LPVOID PerformSearch(__in LPSRCH_CTX lpCTX, __in_bcount(nSize) const PBYTE pcbData, __in INT nSize)
  167. {
  168.     INT i, j;
  169.  
  170.     if (nSize < lpCTX->nLength)
  171.         return NULL;
  172.  
  173.     i = 0;
  174.  
  175.     while (i + lpCTX->nLength - 1 < nSize)
  176.     {
  177.         // 先頭から探索する。
  178.         j = 0;
  179.  
  180.         while (j < lpCTX->nLength && XEqual(lpCTX->vusXPattern[j], pcbData[i + j]))
  181.         {
  182.             // 一致した場合1byte右にずらす。
  183.             j++;
  184.         }
  185.  
  186.         if (j == lpCTX->nLength)
  187.             return pcbData + i;
  188.         else
  189.         {
  190.             // テーブル分右にずらす
  191.             if (i + lpCTX->nLength < nSize)
  192.                 i += lpCTX->iBC[pcbData[i + lpCTX->nLength]];
  193.             else
  194.                 return NULL;
  195.         }
  196.     }
  197.  
  198.     return NULL;
  199. }
  200.  
  201. BOOL InitializeSearch(__out LPSRCH_CTX lpCTX, __in LPCWSTR lpPattern)
  202. {
  203.     if (!GenerateXPattern(lpCTX, lpPattern))
  204.         return FALSE;
  205.  
  206.     CalculateBC(lpCTX);
  207.     return TRUE;
  208. }
  209.  
  210. LPVOID FindPatternA(__in_bcount(nSize) LPCVOID lpcv, __in INT nSize, __in LPCSTR lpPattern)
  211. {
  212.     INT nLength = MultiByteToWideChar(CP_ACP, 0, lpPattern, -1, NULL, 0);
  213.     if (nLength == 0)
  214.         return NULL;
  215.  
  216.     std::unique_ptr<WCHAR> wszBuffer(new WCHAR(nLength));
  217.  
  218.     if (MultiByteToWideChar(CP_ACP, 0, lpPattern, nLength, wszBuffer.get(), nLength) == 0)
  219.         return FALSE;
  220.  
  221.     return FindPatternW(lpcv, nSize, wszBuffer.get());
  222. }
  223.  
  224. LPVOID FindPatternW(__in_bcount(nSize) LPCVOID lpcv, __in INT nSize, __in LPCWSTR lpPattern)
  225. {
  226.     SRCH_CTX ctx;
  227.  
  228.     if (!InitializeSearch(&ctx, lpPattern))
  229.         return FALSE;
  230.  
  231.     return PerformSearch(&ctx, (const PBYTE)lpcv, nSize);
  232. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement