Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.146.221.52] |
|
Сообщ.
#1
,
|
|
|
Здраствуйте, нашё модификацию функции POS, называется PosEx.
Говорят что работает быстрее старой плюс есть возможность указывать на начало позиции поиска, но есть одно но эта функция игнорирует Регистр букв. Помогите модифицировать данную функцию так что бы была опциональная возможность поиска с учетом регистра. примерно так function PosEx2(const substr : AnsiString; const s : AnsiString; StartPos : Cardinal; CaseSense : Boolean) : Integer; function PosEx(const substr : AnsiString; const s : AnsiString; StartPos : Cardinal) : Integer; type StrRec = packed record allocSiz: Longint; refCnt: Longint; length: Longint; end; const skew = sizeof(StrRec); asm { ->EAX Pointer to substr } { EDX Pointer to string } { <-EAX Position of substr in s or 0 } TEST EAX,EAX JE @@noWork TEST EDX,EDX JE @@stringEmpty PUSH EBX PUSH ESI PUSH EDI MOV ESI,EAX { Point ESI to substr } MOV EDI,EDX { Point EDI to s } MOV EAX,ECX MOV ECX,[EDI-skew].StrRec.length { ECX = Length(s) } ADD EDI,EAX SUB ECX,EAX PUSH EDI { remember s position to calculate index } MOV EDX,[ESI-skew].StrRec.length { EDX = Length(substr) } DEC EDX { EDX = Length(substr) - 1 } JS @@fail { < 0 ? return 0 } MOV AL,[ESI] { AL = first char of substr } INC ESI { Point ESI to 2'nd char of substr } SUB ECX,EDX { #positions in s to look at } { = Length(s) - Length(substr) + 1 } JLE @@fail @@loop: REPNE SCASB JNE @@fail MOV EBX,ECX { save outer loop counter } PUSH ESI { save outer loop substr pointer } PUSH EDI { save outer loop s pointer } MOV ECX,EDX REPE CMPSB POP EDI { restore outer loop s pointer } POP ESI { restore outer loop substr pointer } JE @@found MOV ECX,EBX { restore outer loop counter } JMP @@loop @@fail: POP EDX { get rid of saved s pointer } XOR EAX,EAX JMP @@exit @@stringEmpty: XOR EAX,EAX JMP @@noWork @@found: POP EDX { restore pointer to first char of s } MOV EAX,EDI { EDI points of char after match } SUB EAX,EDX { the difference is the correct index } @@exit: POP EDI POP ESI POP EBX @@noWork: end; |
Сообщ.
#2
,
|
|
|
из d2006
function PosEx(const SubStr, S: string; Offset: Integer = 1): Integer; asm test eax, eax jz @Nil test edx, edx jz @Nil dec ecx jl @Nil push esi push ebx mov esi, [edx-4] //Length(Str) mov ebx, [eax-4] //Length(Substr) sub esi, ecx //effective length of Str add edx, ecx //addr of the first char at starting position cmp esi, ebx jl @Past //jump if EffectiveLength(Str)<Length(Substr) test ebx, ebx jle @Past //jump if Length(Substr)<=0 add esp, -12 add ebx, -1 //Length(Substr)-1 add esi, edx //addr of the terminator add edx, ebx //addr of the last char at starting position mov [esp+8], esi //save addr of the terminator add eax, ebx //addr of the last char of Substr sub ecx, edx //-@Str[Length(Substr)] neg ebx //-(Length(Substr)-1) mov [esp+4], ecx //save -@Str[Length(Substr)] mov [esp], ebx //save -(Length(Substr)-1) movzx ecx, byte ptr [eax] //the last char of Substr @Loop: cmp cl, [edx] jz @Test0 @AfterTest0: cmp cl, [edx+1] jz @TestT @AfterTestT: add edx, 4 cmp edx, [esp+8] jb @Continue @EndLoop: add edx, -2 cmp edx, [esp+8] jb @Loop @Exit: add esp, 12 @Past: pop ebx pop esi @Nil: xor eax, eax ret @Continue: cmp cl, [edx-2] jz @Test2 cmp cl, [edx-1] jnz @Loop @Test1: add edx, 1 @Test2: add edx, -2 @Test0: add edx, -1 @TestT: mov esi, [esp] test esi, esi jz @Found @String: movzx ebx, word ptr [esi+eax] cmp bx, word ptr [esi+edx+1] jnz @AfterTestT cmp esi, -2 jge @Found movzx ebx, word ptr [esi+eax+2] cmp bx, word ptr [esi+edx+3] jnz @AfterTestT add esi, 4 jl @String @Found: mov eax, [esp+4] add edx, 2 cmp edx, [esp+8] ja @Exit add esp, 12 add eax, edx pop ebx pop esi end; |
Сообщ.
#3
,
|
|
|
Цитата Ableton @ Говорят что работает быстрее старой плюс есть возможность указывать на начало позиции поиска, но есть одно но эта функция игнорирует Регистр букв. Не игнорирует, а как раз при сравнении учитывают регистр букв! Самый простой способ сделать так, чтобы не учитывали (при сравнении), это: p := Pos(AnsiLowerCase(substr), AnsiLowerCase(s)); p := PosEx(AnsiLowerCase(substr), AnsiLowerCase(s), startPos); Т.е., например, можно сделать такую функцию: function PosEx(const substr, s: string; startPos: integer = 1; caseSense: boolean=true): integer; begin if caseSense then result := SysUtils.PosEx(substr, s, startPos) else result := SysUtils.PosEx(AnsiLowerCase(substr), AnsiLowerCase(s), startPos); end; Функция AnsiLowerCase понижает регистр букв, учитывая язык. Скорость такой функии можно поднять. если составить таблицу трансляции, и использовать её вместо вызовов AnsiLowerCase: function str2lower_init(s: string): string; forward; var str2lower_func: pointer = @str2lower_init; str2lower_xlat: PChar; // таблица трансляции function str2lower_code(s: string): string; asm mov ecx,edx mov edx,str2lower_xlat jmp StrXLat end; function InitStr2Lower: boolean; var lock: TRTLCriticalSection; i: integer; p: pbyte; begin InitializeCriticalSection(lock); result := false; if TryEnterCriticalSection(lock) then try GetMem(str2lower_xlat, 256); p := str2lower_xlat; for i := 0 to 255 do begin p^ := i; inc(p); end; CharLowerBuff(str2lower_xlat, 256); // заполняем таблицу трансляции str2lower_func := @str2lower_code; result := true; except LeaveCriticalSection(lock); end; DeleteCriticalSection(lock); end; function str2lower(s: string): string; asm jmp str2lower_func end; function str2lower_init(s: string): string; begin if InitStr2Lower then result := str2lower(s) else result := AnsiLowerCase(s); end; По тестам str2lower опережает AnsiLowerCase по скорости на 100-300%. |
Сообщ.
#4
,
|
|
|