mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-25 03:07:06 +00:00
66e9d4f5e8
svn-id: r30664
169 lines
3.8 KiB
C++
169 lines
3.8 KiB
C++
/* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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
|
|
|