forked from e-delphi/VCL2FMX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPatchLib.pas
202 lines (169 loc) · 5.47 KB
/
PatchLib.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
{$I InnovaLibDefs.inc}
unit PatchLib;
interface
uses
System.Classes, System.UITypes, System.IOUtils, Winapi.Windows, System.SysUtils, System.Generics.Collections,
Vcl.Imaging.PngImage;
const
CRLF = #13#10;
CR = #13;
LF = #10;
ZSISOffset = 0;
LineTruncLength = 64;
type
TImageList = class(TObjectList<TPngImage>);
function ColorToAlphaColor(const AColor: String): String;
function PosNoCase(const ASubstr: String; AFullString: String; Offset: Integer = 1;
const ASkipChars: TArray<Char> = []): Integer;
function StringReplaceSkipChars(const Source, OldPattern, NewPattern: string): string; overload;
function StringReplaceSkipChars(const Source, OldPattern, NewPattern: string; const ASkipChars: TArray<Char>): string; overload;
procedure PopulateStringsFromArray(AStrings: TStrings; AArray: TArray<String>);
function BreakIntoLines(const AData, APad: String; ALineLen: Integer = LineTruncLength): String;
function StreamToHex(AMemStream:TMemoryStream): String;
procedure HexToStream(AData: string; AMemStream:TMemoryStream);
implementation
uses
System.UIConsts, Vcl.Graphics;
function ColorToAlphaColor(const AColor: String): String;
var
Color, AlphaColor: Integer;
begin
Color := ColorToRGB(StringToColor(AColor));
TAlphaColorRec(AlphaColor).A := 255;
TAlphaColorRec(AlphaColor).B := TColorRec(Color).B;
TAlphaColorRec(AlphaColor).G := TColorRec(Color).G;
TAlphaColorRec(AlphaColor).R := TColorRec(Color).R;
AlphaColorToIdent(AlphaColor, Result);
end;
function CheckSubstr(const AFullString, ASubUp, ASubLow: String; APos: Integer; const ASkipChars: TArray<Char>;
var ASkipCount: Integer): Boolean; inline;
var
i: Integer;
FullChar, SkipChar: Char;
Skip: Boolean;
begin
Result := True;
i := 0;
ASkipCount := 0;
while i < ASubUp.Length + ASkipCount do
begin
Inc(i);
FullChar := AFullString[APos + i];
Skip := False;
for SkipChar in ASkipChars do
if SkipChar = FullChar then
begin
Skip := True;
Inc(ASkipCount);
Break;
end;
if Skip and (i = 1) then
Exit(False);
if (not Skip) and (ASubUp[i - ASkipCount] <> FullChar) and (ASubLow[i - ASkipCount] <> FullChar) then
Exit(False);
end;
end;
function PosNoCase(const ASubstr: String; AFullString: String; Offset: Integer = 1;
const ASkipChars: TArray<Char> = []): Integer;
var
FullLength, SubLength, Temp: Integer;
SubUp, SubLow: String;
begin
Result := 0;
if (AFullString = '') or (ASubstr = '') or (Offset <= 0) then
Exit;
SubLength := ASubstr.Length;
FullLength := AFullString.Length;
if SubLength + Offset - 1 > FullLength then
Exit;
SubUp := ASubstr.ToUpper;
SubLow := ASubstr.ToLower;
Result := Offset - 1;
while SubLength <= (FullLength - Result) do
begin
if CheckSubstr(AFullString, SubUp, SubLow, Result, ASkipChars, Temp) then
Exit(Result + 1)
else
Inc(Result);
end;
Result := 0;
end;
function StringReplaceSkipChars(const Source, OldPattern, NewPattern: string): string;
begin
Result := StringReplaceSkipChars(Source, OldPattern, NewPattern, [CR, LF, ' ']);
end;
function StringReplaceSkipChars(const Source, OldPattern, NewPattern: string; const ASkipChars: TArray<Char>): string;
var
SourceLength, OldLength, SkipCount, Pos, Len, i, PrevEnd: Integer;
PatternStarts, PatternEnds: array of Integer;
OldUp, OldLow: String;
begin
Result := Source;
if (Source = '') or (OldPattern = '') then
Exit;
OldLength := OldPattern.Length;
SourceLength := Source.Length;
if OldLength > SourceLength then
Exit;
OldUp := OldPattern.ToUpper;
OldLow := OldPattern.ToLower;
Pos := 0;
while OldLength <= (SourceLength - Pos) do
begin
if CheckSubstr(Source, OldUp, OldLow, Pos, ASkipChars, SkipCount) then
begin
Len := Length(PatternStarts);
SetLength(PatternStarts, Len + 1);
PatternStarts[Len] := Pos;
Len := Length(PatternEnds);
SetLength(PatternEnds, Len + 1);
PatternEnds[Len] := Pos + OldLength + SkipCount;
Inc(Pos, OldLength + SkipCount)
end
else
Inc(Pos);
end;
Result := '';
PrevEnd := 0;
for i := 0 to High(PatternStarts) do
begin
Result := Result + Source.Substring(PrevEnd, PatternStarts[i] - PrevEnd) + NewPattern;
PrevEnd := PatternEnds[i];
end;
Result := Result + Source.Substring(PrevEnd);
end;
procedure PopulateStringsFromArray(AStrings: TStrings; AArray: TArray<String>);
var
i: Integer;
begin
if AStrings = nil then
raise Exception.Create('PopulateStringsFromArray');
AStrings.Clear;
for i := 0 to high(AArray) do
AStrings.Add(AArray[i].Trim);
end;
function StreamToHex(AMemStream:TMemoryStream): String;
begin
SetLength(Result, AMemStream.Size * 2);
BinToHex(AMemStream.Memory^, PChar(Result), AMemStream.Size);
end;
function BreakIntoLines(const AData, APad: String; ALineLen: Integer = LineTruncLength): String;
var
Line: String;
LineNum: Integer;
begin
Result := '';
LineNum := 0;
repeat
Line := Copy(AData, ALineLen * LineNum + 1, ALineLen);
if Line <> '' then
Result := Result + CRLF + APad + ' ' + Line;
Inc(LineNum);
until Length(Line) < ALineLen;
end;
procedure HexToStream(AData: string; AMemStream:TMemoryStream);
begin
AMemStream.Size := Length(AData) div 2;
HexToBin(PChar(AData), AMemStream.Memory^, AMemStream.Size);
end;
end.