whats new ¦  programming tips ¦  indy articles ¦  intraweb articles ¦  informations ¦  links ¦  interviews
misc ¦  tutorials ¦  Add&Win Game

 27 Visitors Online

 ...Find a Substring in a String starting from any position in the String? Autor: cnsSmartPos [ Print tip ]

 Tip Rating (23):

//-----------------------------------------------------------------------------
// Name: cnsSmartPos
// Author: Com-N-Sense
// Date:
// Purpose: Find a substring in a string starting from any position in the string.
// Params: SubStr - a substring for search.
//         S - the source string to search within
//         StartPos - the index position to start the search.
// Result: Integer - the position of the substring,
//                   zero - if the substring was not found
// Remarks: This is the original Delphi "Pos" function modified to support
//          the start pos parameter.
//-----------------------------------------------------------------------------
function SmartPosAsm(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)               }

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//SmartPosAsm

function cnsSmartPos(const substr : AnsiString; const s : AnsiString; StartPos : Cardinal) : Integer;
begin

dec(StartPos);
Result := SmartPosAsm(SubStr,S,StartPos);
if Result > 0 then Result := Result + StartPos;
end//cnsSmartPos

Rate this tip:

 poor very good