📄 jclstrings.pas
字号:
// ebx will hold the case map, esi pointer to Str
PUSH EBX
PUSH ESI
PUSH EDI
// load case map and prepare variables }
{$IFDEF PIC}
LEA EBX, [EBX][AnsiCaseMap + EDX]
{$ELSE}
LEA EBX, [AnsiCaseMap + EDX]
{$ENDIF PIC}
MOV ESI, EAX
XOR EDX, EDX
XOR EAX, EAX
@@NextChar:
// get current char from the AnsiString
MOV DL, [ESI]
// get corresponding char from the case map
MOV AL, [EBX + EDX]
// store it back in the string
MOV [ESI], AL
// update the loop counter and check the end of stirng
DEC ECX
JL @@Done
// do the same thing with next 3 chars
MOV DL, [ESI + 1]
MOV AL, [EBX + EDX]
MOV [ESI + 1], AL
DEC ECX
JL @@Done
MOV DL, [ESI + 2]
MOV AL, [EBX+EDX]
MOV [ESI + 2], AL
DEC ECX
JL @@Done
MOV DL, [ESI + 3]
MOV AL, [EBX + EDX]
MOV [ESI + 3], AL
// point AnsiString to next 4 chars
ADD ESI, 4
// update the loop counter and check the end of stirng
DEC ECX
JGE @@NextChar
@@Done:
POP EDI
POP ESI
POP EBX
@@StrIsNull:
end;
// Internal utility function
// Uppercases or Lowercases a give null terminated string depending on the
// passed offset. (UpOffset or LoOffset)
procedure StrCaseBuff(S: PAnsiChar; const Offset: Integer); register; assembler;
asm
// make sure the string is not null
TEST EAX, EAX
JZ @@StrIsNull
// ebx will hold the case map, esi pointer to Str
PUSH EBX
PUSH ESI
// load case map and prepare variables
{$IFDEF PIC}
LEA EBX, [EBX][AnsiCaseMap + EDX]
{$ELSE}
LEA EBX, [AnsiCaseMap + EDX]
{$ENDIF PIC}
MOV ESI, EAX
XOR EDX, EDX
XOR EAX, EAX
@@NextChar:
// get current char from the string
MOV DL, [ESI]
// check for null char
TEST DL, DL
JZ @@Done
// get corresponding char from the case map
MOV AL, [EBX + EDX]
// store it back in the string
MOV [ESI], AL
// do the same thing with next 3 chars
MOV DL, [ESI + 1]
TEST DL, DL
JZ @@Done
MOV AL, [EBX+EDX]
MOV [ESI + 1], AL
MOV DL, [ESI + 2]
TEST DL, DL
JZ @@Done
MOV AL, [EBX+EDX]
MOV [ESI + 2], AL
MOV DL, [ESI + 3]
TEST DL, DL
JZ @@Done
MOV AL, [EBX+EDX]
MOV [ESI + 3], AL
// point string to next 4 chars
ADD ESI, 4
JMP @@NextChar
@@Done:
POP ESI
POP EBX
@@StrIsNull:
end;
function StrEndW(Str: PWideChar): PWideChar;
// returns a pointer to the end of a null terminated string
// stolen from JclUnicode
asm
MOV EDX, EDI
MOV EDI, EAX
MOV ECX, 0FFFFFFFFH
XOR AX, AX
REPNE SCASW
LEA EAX, [EDI - 2]
MOV EDI, EDX
end;
// String Test Routines
function StrIsAlpha(const S: AnsiString): Boolean;
var
I: Integer;
begin
Result := S <> '';
for I := 1 to Length(S) do
begin
if not CharIsAlpha(S[I]) then
begin
Result := False;
Exit;
end;
end;
end;
function StrIsAlphaNum(const S: AnsiString): Boolean;
var
I: Integer;
begin
Result := S <> '';
for I := 1 to Length(S) do
begin
if not CharIsAlphaNum(S[I]) then
begin
Result := False;
Exit;
end;
end;
end;
function StrConsistsofNumberChars(const S: AnsiString): Boolean;
var
I: Integer;
begin
Result := S <> '';
for I := 1 to Length(S) do
begin
if not CharIsNumberChar(S[I]) then
begin
Result := False;
Exit;
end;
end;
end;
function StrContainsChars(const S: AnsiString; Chars: TSysCharSet; CheckAll: Boolean): Boolean;
var
I: Integer;
C: Char;
begin
Result := Chars = [];
if not Result then
begin
if CheckAll then
begin
for I := 1 to Length(S) do
begin
C := S[I];
if C in Chars then
begin
Chars := Chars - [C];
if Chars = [] then
Break;
end;
end;
Result := (Chars = []);
end
else
begin
for I := 1 to Length(S) do
if S[I] in Chars then
begin
Result := True;
Break;
end;
end;
end;
end;
function StrIsAlphaNumUnderscore(const S: AnsiString): Boolean;
var
I: Integer;
C: AnsiChar;
begin
for i := 1 to Length(s) do
begin
C := S[I];
if not (CharIsAlphaNum(C) or (C = '_')) then
begin
Result := False;
Exit;
end;
end;
Result := True and (Length(S) > 0);
end;
function StrIsDigit(const S: AnsiString): Boolean;
var
I: Integer;
begin
Result := S <> '';
for I := 1 to Length(S) do
begin
if not CharIsDigit(S[I]) then
begin
Result := False;
Exit;
end;
end;
end;
function StrIsSubset(const S: AnsiString; const ValidChars: TSysCharSet): Boolean;
var
I: Integer;
begin
for I := 1 to Length(S) do
begin
if not (S[I] in ValidChars) then
begin
Result := False;
Exit;
end;
end;
Result := True and (Length(S) > 0);
end;
function StrSame(const S1, S2: AnsiString): Boolean;
begin
Result := StrCompare(S1, S2) = 0;
end;
//=== String Transformation Routines =========================================
function StrCenter(const S: AnsiString; L: Integer; C: AnsiChar = ' '): AnsiString;
begin
if Length(S) < L then
begin
Result := StringOfChar(C, (L - Length(S)) div 2) + S;
Result := Result + StringOfChar(C, L - Length(Result));
end
else
Result := S;
end;
function StrCharPosLower(const S: AnsiString; CharPos: Integer): AnsiString;
begin
Result := S;
if (CharPos > 0) and (CharPos <= Length(S)) then
Result[CharPos] := JclStrings.CharLower(Result[CharPos]);
end;
function StrCharPosUpper(const S: AnsiString; CharPos: Integer): AnsiString;
begin
Result := S;
if (CharPos > 0) and (CharPos <= Length(S)) then
Result[CharPos] := CharUpper(Result[CharPos]);
end;
function StrDoubleQuote(const S: AnsiString): AnsiString;
begin
Result := AnsiDoubleQuote + S + AnsiDoubleQuote;
end;
function StrEnsureNoPrefix(const Prefix, Text: AnsiString): AnsiString;
var
PrefixLen : Integer;
begin
PrefixLen := Length(Prefix);
if Copy(Text, 1, PrefixLen) = Prefix then
Result := Copy(Text, PrefixLen + 1, Length(Text))
else
Result := Text;
end;
function StrEnsureNoSuffix(const Suffix, Text: AnsiString): AnsiString;
var
SuffixLen : Integer;
StrLength : Integer;
begin
SuffixLen := Length(Suffix);
StrLength := Length(Text);
if Copy(Text, StrLength - SuffixLen + 1, SuffixLen) = Suffix then
Result := Copy(Text, 1, StrLength - SuffixLen)
else
Result := Text;
end;
function StrEnsurePrefix(const Prefix, Text: AnsiString): AnsiString;
var
PrefixLen: Integer;
begin
PrefixLen := Length(Prefix);
if Copy(Text, 1, PrefixLen) = Prefix then
Result := Text
else
Result := Prefix + Text;
end;
function StrEnsureSuffix(const Suffix, Text: AnsiString): AnsiString;
var
SuffixLen: Integer;
begin
SuffixLen := Length(Suffix);
if Copy(Text, Length(Text) - SuffixLen + 1, SuffixLen) = Suffix then
Result := Text
else
Result := Text + Suffix;
end;
function StrEscapedToString(const S: AnsiString): AnsiString;
var
I, Len, N, Val: Integer;
procedure HandleHexEscapeSeq;
const
HexDigits = AnsiString('0123456789abcdefABCDEF');
begin
N := Pos(S[I + 1], HexDigits) - 1;
if N < 0 then
// '\x' without hex digit following is not escape sequence
Result := Result + '\x'
else
begin
Inc(I); // Jump over x
if N >= 16 then
N := N - 6;
Val := N;
// Same for second digit
if I < Len then
begin
N := Pos(S[I + 1], HexDigits) - 1;
if N >= 0 then
begin
Inc(I); // Jump over first digit
if N >= 16 then
N := N - 6;
Val := Val * 16 + N;
end;
end;
if val > 255 then
raise EJclStringError.CreateRes(@RsNumericConstantTooLarge);
Result := Result + Chr(Val);
end;
end;
procedure HandleOctEscapeSeq;
const
OctDigits = AnsiString('01234567');
begin
// first digit
Val := Pos(S[I], OctDigits) - 1;
if I < Len then
begin
N := Pos(S[I + 1], OctDigits) - 1;
if N >= 0 then
begin
Inc(I);
Val := Val * 8 + N;
end;
if I < Len then
begin
N := Pos(S[I + 1], OctDigits) - 1;
if N >= 0 then
begin
Inc(I);
Val := Val * 8 + N;
end;
end;
end;
if val > 255 then
raise EJclStringError.CreateRes(@RsNumericConstantTooLarge);
Result := Result + Chr(Val);
end;
begin
Result := '';
I := 1;
Len := Length(S);
while I <= Len do
begin
if not ((S[I] = '\') and (I < Len)) then
Result := Result + S[I]
else
begin
Inc(I); // Jump over escape character
case S[I] of
'a':
Result := Result + AnsiBell;
'b':
Result := Result + AnsiBackspace;
'f':
Result := Result + AnsiFormFeed;
'n':
Result := Result + AnsiLineFeed;
'r':
Result := Result + AnsiCarriageReturn;
't':
Result := Result + AnsiTab;
'v':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -