📄 rm_jclstrings.pas.~1~
字号:
function StrRefCount(const S: string): Longint;
var
P: Pointer;
begin
Result := 0;
if Pointer(S) <> nil then
begin
P := Pointer(Integer(Pointer(S)) - AnsiRfOffset);
Result := Integer(P^);
end;
end;
{$ENDIF ~CLR}
procedure StrResetLength(var S: string);
{$IFDEF CLR}
var
I: Integer;
{$ENDIF CLR}
begin
{$IFDEF CLR}
for I := 1 to Length(S) do
if S[I] = #0 then
begin
SetLength(S, I);
Exit;
end;
{$ELSE}
SetLength(S, StrLen(PChar(S)));
{$ENDIF CLR}
end;
{$IFDEF CLR}
procedure StrResetLength(S: StringBuilder);
var
I: Integer;
begin
for I := 0 to S.Length - 1 do
if S[I] = #0 then
begin
S.Length := I + 1;
Exit;
end;
end;
{$ENDIF CLR}
//=== String Search and Replace Routines =====================================
function StrCharCount(const S: string; C: Char): Integer;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(S) do
if S[I] = C then
Inc(Result);
end;
function StrCharsCount(const S: string; Chars: TSysCharSet): Integer;
var
I: Integer;
begin
Result := 0;
for I := 1 to Length(S) do
if S[I] in Chars then
Inc(Result);
end;
function StrStrCount(const S, SubS: string): Integer;
var
I: Integer;
begin
Result := 0;
if (Length(SubS) > Length(S)) or (Length(SubS) = 0) or (Length(S) = 0) then
Exit;
if Length(SubS) = 1 then
begin
Result := StrCharCount(S, SubS[1]);
Exit;
end;
I := StrSearch(SubS, S, 1);
if I > 0 then
Inc(Result);
while (I > 0) and (Length(S) > I+Length(SubS)) do
begin
I := StrSearch(SubS, S, I+1);
if I > 0 then
Inc(Result);
end
end;
{$IFDEF CLR}
function StrCompare(const S1, S2: string): Integer;
begin
Result := S1.CompareTo(S2);
end;
{$ELSE}
{$IFDEF PIC}
function _StrCompare(const S1, S2: string): Integer; forward;
function StrCompare(const S1, S2: string): Integer;
begin
Result := _StrCompare(S1, S2);
end;
function _StrCompare(const S1, S2: string): Integer; assembler;
{$ELSE}
function StrCompare(const S1, S2: string): Integer; assembler;
{$ENDIF PIC}
asm
// check if pointers are equal
CMP EAX, EDX
JE @@Equal
// if S1 is nil return - Length(S2)
TEST EAX, EAX
JZ @@Str1Null
// if S2 is nil return Length(S1)
TEST EDX, EDX
JZ @@Str2Null
// EBX will hold case map, ESI S1, EDI S2
PUSH EBX
PUSH ESI
PUSH EDI
// move string pointers
MOV ESI, EAX
MOV EDI, EDX
// get the length of strings
MOV EAX, [ESI-AnsiStrRecSize].TAnsiStrRec.Length
MOV EDX, [EDI-AnsiStrRecSize].TAnsiStrRec.Length
// exit if Length(S1) <> Length(S2)
CMP EAX, EDX
JNE @@MissMatch
// check the length just in case
DEC EDX
JS @@InvalidStr
DEC EAX
JS @@InvalidStr
// load case map
LEA EBX, AnsiCaseMap
// make ECX our loop counter
MOV ECX, EAX
// clear working regs
XOR EAX, EAX
XOR EDX, EDX
// get last chars
MOV AL, [ESI+ECX]
MOV DL, [EDI+ECX]
// lower case them
MOV AL, [EBX+EAX]
MOV DL, [EBX+EDX]
// compare them
CMP AL, DL
JNE @@MissMatch
// if there was only 1 char then exit
JECXZ @@Match
@@NextChar:
// case sensitive compare of strings
REPE CMPSB
JE @@Match
// if there was a missmatch try case insensitive compare, get the chars
MOV AL, [ESI-1]
MOV DL, [EDI-1]
// lowercase and compare them, if equal then continue
MOV AL, [EBX+EAX]
MOV DL, [EBX+EDX]
CMP AL, DL
JE @@NextChar
// if we make it here then strings don't match, return the difference
@@MissMatch:
SUB EAX, EDX
POP EDI
POP ESI
POP EBX
RET
@@Match:
// match, return 0
XOR EAX, EAX
POP EDI
POP ESI
POP EBX
RET
@@InvalidStr:
XOR EAX, EAX
DEC EAX
POP EDI
POP ESI
POP EBX
RET
@@Str1Null:
// return = - Length(Str2);
MOV EDX, [EDX-AnsiStrRecSize].TAnsiStrRec.Length
SUB EAX, EDX
RET
@@Str2Null:
// return = Length(Str2);
MOV EAX, [EAX-AnsiStrRecSize].TAnsiStrRec.Length
RET
@@Equal:
XOR EAX, EAX
end;
{$ENDIF CLR}
{$IFDEF CLR}
function StrCompareRange(const S1, S2: string; const Index, Count: Integer): Integer;
begin
Result := System.String.Compare(S1, Index - 1, S2, Index - 1, Count, False);
end;
{$ELSE}
function StrCompareRange(const S1, S2: string; const Index, Count: Integer): Integer; assembler;
asm
TEST EAX, EAX
JZ @@Str1Null
TEST EDX, EDX
JZ @@StrNull
DEC ECX
JS @@StrNull
PUSH EBX
PUSH ESI
PUSH EDI
MOV EBX, Count
DEC EBX
JS @@NoWork
MOV ESI, EAX
MOV EDI, EDX
MOV EDX, [ESI - AnsiStrRecSize].TAnsiStrRec.Length
// # of chars in S1 - (Index - 1)
SUB EDX, ECX
JLE @@NoWork
// # of chars in S1 - (Count - 1)
SUB EDX, EBX
JLE @@NoWork
// move to index'th char
ADD ESI, ECX
MOV ECX, [EDI - AnsiStrRecSize].TAnsiStrRec.Length
DEC ECX
JS @@NoWork
// if Length(S2) > Count then ECX := Count else ECX := Length(S2)
CMP ECX, EBX
JLE @@Skip1
MOV ECX, EBX
@@Skip1:
XOR EAX, EAX
XOR EDX, EDX
@@Loop:
MOV AL, [ESI]
INC ESI
MOV DL, [EDI]
INC EDI
CMP AL, DL
JNE @@MisMatch
DEC ECX
JGE @@Loop
@@Match:
XOR EAX, EAX
POP EDI
POP ESI
POP EBX
JMP @@Exit
@@MisMatch:
SUB EAX, EDX
POP EDI
POP ESI
POP EBX
JMP @@Exit
@@NoWork:
MOV EAX, -2
POP EDI
POP ESI
POP EBX
JMP @@Exit
@@Str1Null:
MOV EAX, 0
TEST EDX, EDX
JZ @@Exit
@@StrNull:
MOV EAX, -1
@@Exit:
end;
{$ENDIF CLR}
function StrFillChar(const C: Char; Count: Integer): string;
{$IFDEF CLR}
var
sb: StringBuilder;
begin
sb := StringBuilder.Create(Count);
while Count > 0 do
begin
sb.Append(C);
Dec(Count);
end;
Result := sb.ToString();
end;
{$ELSE}
begin
SetLength(Result, Count);
if (Count > 0) then
FillChar(Result[1], Count, Ord(C));
end;
{$ENDIF CLR}
{$IFDEF CLR}
function StrFind(const Substr, S: string; const Index: Integer): Integer;
begin
Result := System.String(S).ToLower().IndexOf(System.String(SubStr).ToLower(), Index - 1) + 1;
end;
{$ELSE}
function StrFind(const Substr, S: string; const Index: Integer): Integer; assembler;
const
SearchChar: Byte = 0;
NumberOfChars: Integer = 0;
asm
// if SubStr = '' then Return := 0;
TEST EAX, EAX
JZ @@SubstrIsNull
// if Str = '' then Return := 0;
TEST EDX, EDX
JZ @@StrIsNull
// Index := Index - 1; if Index < 0 then Return := 0;
DEC ECX
JL @@IndexIsSmall
// EBX will hold the case table, ESI pointer to Str, EDI pointer
// to Substr and - # of chars in Substr to compare
PUSH EBX
PUSH ESI
PUSH EDI
// set the string pointers
MOV ESI, EDX
MOV EDI, EAX
// save the Index in EDX
MOV EDX, ECX
// temporary get the length of Substr and Str
MOV EBX, [EDI - AnsiStrRecSize].TAnsiStrRec.Length
MOV ECX, [ESI - AnsiStrRecSize].TAnsiStrRec.Length
// save the address of Str to compute the result
PUSH ESI
// dec the length of Substr because the first char is brought out of it
DEC EBX
JS @@NotFound
// #positions in Str to look at = Length(Str) - Length(Substr) - Index - 2
SUB ECX, EBX
JLE @@NotFound
SUB ECX, EDX
JLE @@NotFound
// # of chars in Substr to compare
MOV NumberOfChars, EBX
// point Str to Index'th char
ADD ESI, EDX
// load case map into EBX, and clear EAX
LEA EBX, AnsiCaseMap
XOR EAX, EAX
XOR EDX, EDX
// bring the first char out of the Substr and point Substr to the next char
MOV DL, [EDI]
INC EDI
// lower case it
MOV DL, [EBX + EDX]
MOV SearchChar, DL
JMP @@Find
@@FindNext:
// update the loop counter and check the end of string.
// if we reached the end, Substr was not found.
DEC ECX
JL @@NotFound
@@Find:
// get current char fro
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -