/* ScummVM Tools * Copyright (C) 2007 The ScummVM project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ #include "stdafx.h" #include "KmpSearch.h" #include #include #include #ifdef _MSC_VER __declspec(naked) void __fastcall KmpSearch::init(const char *subStr) { __asm { // kmp initialization, make jump table for mismatches push esi push edi push ebp push ebx push ecx mov esi, edx // edx: subStr argument lea edi, [ecx + KmpSearch::_subStr] // this + 0x100 lea ebx, [ecx + KmpSearch::_retarget] // this lea ebp, [ecx + 1] mov byte ptr [ebx], -1 xor eax, eax loopStart: shr ecx, 8 test al, 3 jnz short dontLoad mov ecx, dword ptr [esi + eax] // load next 4 bytes of subStr mov dword ptr [edi], ecx // and copy them to this._subStr while we're at it lea edi, [edi + 4] dontLoad: or cl, cl // end of subStr? jz short endOfString mov edx, eax // save counter (i) in edx xlat // al = retarget[i] inc al mov byte ptr [ebp + edx], al // retarget[i + 1] = retarget[i] + 1 jz short decLoopEnd decrementLoop: dec al mov ah, byte ptr [esi + eax] // ah = sub[retarget[i + 1] - 1] cmp ah, cl // if (ah == sub[i]) jz short decLoopEnd // goto decLoopEnd xlat // al = retarget[retarget[i + 1] - 1] xor ah, ah inc al // al = retarget[retarget[i + 1] - 1] + 1 mov byte ptr [ebp + edx], al // retarget[i + 1] = al jnz short decrementLoop decLoopEnd: lea eax, [edx + 1] // i = i + 1 jmp short loopStart endOfString: pop ecx // this mov [ecx + KmpSearch::_strLen], eax // length of substring (without '\0') pop ebx pop ebp pop edi pop esi ret } } __declspec(naked) char * __fastcall KmpSearch::search(const char *str) { __asm { push esi push edi push ebx mov esi, edx // edx: str argument lea edi, [ecx + KmpSearch::_subStr] lea ebx, [ecx + KmpSearch::_retarget] mov ch, byte ptr [ecx + KmpSearch::_strLen] or ch, ch // if (_strLen == 0) jz short endOfString // goto endOfString xor edx, edx // index mov cl, 3 searchLoop: shr eax, 8 inc cl test cl, 4 jz short skipRead lodsd xor cl, cl skipRead: test al, al jz short endOfString newIndexLoop: cmp al, byte ptr [edi + edx] // while (c != sub[index]) { jz short gotNewIndex or edx, edx // if (index == 0) jz short searchLoop // goto searchLoop movzx edx, byte ptr [ebx + edx] // index = retarget[index] jmp short newIndexLoop // } gotNewIndex: inc edx cmp dl, ch // if (index != _strLen) jne short searchLoop // goto searchLoop movzx ebx, cl // bytes of eax used movzx ecx, ch // length of subStr lea eax, [esi + ebx - 3] sub eax, ecx pop ebx pop edi pop esi ret endOfString: xor eax, eax // return NULL pop ebx pop edi pop esi ret } } #else void __fastcall KmpSearch::init(const char *subStr) { strcpy(_subStr, subStr); } char * __fastcall KmpSearch::search(const char *str) { return strstr(str, _subStr); } #endif