update to 0.5.2
This commit is contained in:
parent
39fb5ae479
commit
580541c8a3
|
@ -0,0 +1,165 @@
|
||||||
|
unit IOArchive;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Threading, Utils, SynCommons, SynCrypto, ParseClass, ParseExpr,
|
||||||
|
IOUtils,
|
||||||
|
WinAPI.Windows, WinAPI.ShlObj,
|
||||||
|
System.SysUtils, System.Classes, System.SyncObjs, System.Math, System.Types,
|
||||||
|
System.StrUtils, System.RTLConsts, System.TimeSpan, System.Diagnostics,
|
||||||
|
System.IOUtils, System.Generics.Defaults, System.Generics.Collections;
|
||||||
|
|
||||||
|
type
|
||||||
|
PEncodeOptions = ^TEncodeOptions;
|
||||||
|
|
||||||
|
TEncodeOptions = record
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
PDecodeOptions = ^TDecodeOptions;
|
||||||
|
|
||||||
|
TDecodeOptions = record
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure PrintHelp;
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TEncodeOptions);
|
||||||
|
overload;
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TDecodeOptions);
|
||||||
|
overload;
|
||||||
|
procedure Encode(Input: TArray<string>; Output: TStream;
|
||||||
|
Options: TEncodeOptions);
|
||||||
|
procedure Decode(Input: TStream; Output: String; Options: TDecodeOptions);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
procedure PrintHelp;
|
||||||
|
var
|
||||||
|
I, J: Integer;
|
||||||
|
S: string;
|
||||||
|
begin
|
||||||
|
WriteLn(ErrOutput, 'archive - convert a group of files into an archive');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
WriteLn(ErrOutput, 'Usage:');
|
||||||
|
WriteLn(ErrOutput, ' xtool archive files1 files2... archive');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TEncodeOptions);
|
||||||
|
var
|
||||||
|
ArgParse: TArgParser;
|
||||||
|
ExpParse: TExpressionParser;
|
||||||
|
S: String;
|
||||||
|
begin
|
||||||
|
ArgParse := TArgParser.Create(ParamArg);
|
||||||
|
ExpParse := TExpressionParser.Create;
|
||||||
|
try
|
||||||
|
S := '';
|
||||||
|
finally
|
||||||
|
ArgParse.Free;
|
||||||
|
ExpParse.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TDecodeOptions);
|
||||||
|
var
|
||||||
|
ArgParse: TArgParser;
|
||||||
|
ExpParse: TExpressionParser;
|
||||||
|
S: String;
|
||||||
|
begin
|
||||||
|
ArgParse := TArgParser.Create(ParamArg);
|
||||||
|
ExpParse := TExpressionParser.Create;
|
||||||
|
try
|
||||||
|
S := '';
|
||||||
|
finally
|
||||||
|
ArgParse.Free;
|
||||||
|
ExpParse.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Encode(Input: TArray<string>; Output: TStream;
|
||||||
|
Options: TEncodeOptions);
|
||||||
|
var
|
||||||
|
I, J: Integer;
|
||||||
|
K: Word;
|
||||||
|
I64: Int64;
|
||||||
|
BaseDir: String;
|
||||||
|
LList: TArray<String>;
|
||||||
|
LBytes: TBytes;
|
||||||
|
FStream: TFileStream;
|
||||||
|
begin
|
||||||
|
I := XTOOL_ARCH;
|
||||||
|
Output.WriteBuffer(I, I.Size);
|
||||||
|
for I := Low(Input) to High(Input) do
|
||||||
|
begin
|
||||||
|
if FileExists(Input[I]) then
|
||||||
|
BaseDir := ExtractFilePath(TPath.GetFullPath(Input[I]))
|
||||||
|
else if DirectoryExists(Input[I]) then
|
||||||
|
BaseDir := IncludeTrailingBackSlash(TPath.GetFullPath(Input[I]))
|
||||||
|
else
|
||||||
|
BaseDir := ExtractFilePath(TPath.GetFullPath(Input[I]));
|
||||||
|
LList := GetFileList([Input[I]], True);
|
||||||
|
if Length(LList) > 0 then
|
||||||
|
begin
|
||||||
|
J := Length(LList);
|
||||||
|
Output.WriteBuffer(J, J.Size);
|
||||||
|
for J := Low(LList) to High(LList) do
|
||||||
|
begin
|
||||||
|
LBytes := BytesOf(ReplaceText(LList[I], BaseDir, ''));
|
||||||
|
K := Length(LBytes);
|
||||||
|
Output.WriteBuffer(K, K.Size);
|
||||||
|
Output.WriteBuffer(LBytes[0], K);
|
||||||
|
I64 := FileSize(LList[I]);
|
||||||
|
Output.WriteBuffer(I64, I64.Size);
|
||||||
|
FStream := TFileStream.Create(LList[I], fmShareDenyNone);
|
||||||
|
try
|
||||||
|
CopyStreamEx(FStream, Output, I64);
|
||||||
|
finally
|
||||||
|
FStream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
J := J.MinValue;
|
||||||
|
Output.WriteBuffer(J, J.Size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Decode(Input: TStream; Output: String; Options: TDecodeOptions);
|
||||||
|
var
|
||||||
|
I, J: Integer;
|
||||||
|
K: Word;
|
||||||
|
I64: Int64;
|
||||||
|
S: String;
|
||||||
|
BaseDir: String;
|
||||||
|
LBytes: TBytes;
|
||||||
|
FStream: TFileStream;
|
||||||
|
begin
|
||||||
|
BaseDir := IncludeTrailingBackSlash(Output);
|
||||||
|
Input.ReadBuffer(I, I.Size);
|
||||||
|
while I >= 0 do
|
||||||
|
begin
|
||||||
|
for J := 1 to I do
|
||||||
|
begin
|
||||||
|
Input.ReadBuffer(K, K.Size);
|
||||||
|
if Length(LBytes) < K then
|
||||||
|
SetLength(LBytes, K);
|
||||||
|
FillChar(LBytes[0], Length(LBytes), 0);
|
||||||
|
Input.ReadBuffer(LBytes[0], K);
|
||||||
|
S := BaseDir + StringOf(LBytes);
|
||||||
|
if not DirectoryExists(ExtractFilePath(S)) then
|
||||||
|
ForceDirectories(ExtractFilePath(S));
|
||||||
|
Input.ReadBuffer(I64, I64.Size);
|
||||||
|
FStream := TFileStream.Create(S, fmCreate);
|
||||||
|
try
|
||||||
|
CopyStreamEx(Input, FStream, I64);
|
||||||
|
finally
|
||||||
|
FStream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Input.ReadBuffer(I, I.Size);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
|
@ -0,0 +1,477 @@
|
||||||
|
unit IOExecute;
|
||||||
|
|
||||||
|
(* xbcm:t4:c256m
|
||||||
|
xtool execute {options} - - <stdin> <stdout> bcm.exe -9 [filein] [fileout]
|
||||||
|
xtool decode {options} - - <stdin> <stdout> bcm.exe -d [filein] [fileout] *)
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Threading, Utils, SynCommons, SynCrypto, ParseClass, ParseExpr,
|
||||||
|
IOUtils,
|
||||||
|
WinAPI.Windows, WinAPI.ShlObj,
|
||||||
|
System.SysUtils, System.Classes, System.SyncObjs, System.Math, System.Types,
|
||||||
|
System.StrUtils, System.RTLConsts, System.TimeSpan, System.Diagnostics,
|
||||||
|
System.IOUtils, System.Generics.Defaults, System.Generics.Collections;
|
||||||
|
|
||||||
|
type
|
||||||
|
PEncodeOptions = ^TEncodeOptions;
|
||||||
|
|
||||||
|
TEncodeOptions = record
|
||||||
|
ChunkSize, Threads: Integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
PDecodeOptions = ^TDecodeOptions;
|
||||||
|
|
||||||
|
TDecodeOptions = record
|
||||||
|
Threads: Integer;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure PrintHelp;
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TEncodeOptions);
|
||||||
|
overload;
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TDecodeOptions);
|
||||||
|
overload;
|
||||||
|
procedure Encode(Input, Output: TStream; ParamArg: TArray<string>;
|
||||||
|
Options: TEncodeOptions);
|
||||||
|
procedure Decode(Input, Output: TStream; ParamArg: TArray<string>;
|
||||||
|
Options: TDecodeOptions);
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
const
|
||||||
|
FILE_IN = 'data.in';
|
||||||
|
FILE_OUT = 'data.out';
|
||||||
|
FILE_MODE = 0;
|
||||||
|
STDIN_MODE = 1;
|
||||||
|
STDOUT_MODE = 2;
|
||||||
|
STDIO_MODE = 3;
|
||||||
|
STATE_READY = 0;
|
||||||
|
STATE_EXECUTED = 1;
|
||||||
|
STATE_ERROR = 2;
|
||||||
|
STATE_DONE = 3;
|
||||||
|
|
||||||
|
procedure PrintHelp;
|
||||||
|
var
|
||||||
|
I, J: Integer;
|
||||||
|
S: string;
|
||||||
|
begin
|
||||||
|
WriteLn(ErrOutput, 'execute - parallel program execution');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
WriteLn(ErrOutput, 'Usage:');
|
||||||
|
WriteLn(ErrOutput, ' xtool execute [parameters] input output [exec_syntax]');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
WriteLn(ErrOutput, 'Parameters:');
|
||||||
|
WriteLn(ErrOutput, ' -c# - chunk size [16mb]');
|
||||||
|
WriteLn(ErrOutput, ' -t# - number of working threads [50p]');
|
||||||
|
WriteLn(ErrOutput, '');
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TEncodeOptions);
|
||||||
|
var
|
||||||
|
ArgParse: TArgParser;
|
||||||
|
ExpParse: TExpressionParser;
|
||||||
|
I: Integer;
|
||||||
|
S: String;
|
||||||
|
begin
|
||||||
|
ArgParse := TArgParser.Create(ParamArg);
|
||||||
|
ExpParse := TExpressionParser.Create;
|
||||||
|
try
|
||||||
|
S := ArgParse.AsString('-c', 0, '16mb');
|
||||||
|
S := ReplaceText(S, 'KB', '* 1024^1');
|
||||||
|
S := ReplaceText(S, 'MB', '* 1024^2');
|
||||||
|
S := ReplaceText(S, 'GB', '* 1024^3');
|
||||||
|
S := ReplaceText(S, 'K', '* 1024^1');
|
||||||
|
S := ReplaceText(S, 'M', '* 1024^2');
|
||||||
|
S := ReplaceText(S, 'G', '* 1024^3');
|
||||||
|
Options.ChunkSize := Max(4194304, Round(ExpParse.Evaluate(S)));
|
||||||
|
S := ArgParse.AsString('-t', 0, '50p');
|
||||||
|
S := ReplaceText(S, 'p', '%');
|
||||||
|
S := ReplaceText(S, '%', '%*' + CPUCount.ToString);
|
||||||
|
Options.Threads := Max(1, Round(ExpParse.Evaluate(S)));
|
||||||
|
finally
|
||||||
|
ArgParse.Free;
|
||||||
|
ExpParse.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Parse(ParamArg: TArray<string>; out Options: TDecodeOptions);
|
||||||
|
var
|
||||||
|
ArgParse: TArgParser;
|
||||||
|
ExpParse: TExpressionParser;
|
||||||
|
S: String;
|
||||||
|
begin
|
||||||
|
ArgParse := TArgParser.Create(ParamArg);
|
||||||
|
ExpParse := TExpressionParser.Create;
|
||||||
|
try
|
||||||
|
S := ArgParse.AsString('-t', 0, '50p');
|
||||||
|
S := ReplaceText(S, 'p', '%');
|
||||||
|
S := ReplaceText(S, '%', '%*' + CPUCount.ToString);
|
||||||
|
Options.Threads := Max(1, Round(ExpParse.Evaluate(S)));
|
||||||
|
finally
|
||||||
|
ArgParse.Free;
|
||||||
|
ExpParse.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ExtractStr(SubStr, Str: String): String;
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
begin
|
||||||
|
Result := Str.Substring(Str.IndexOf(SubStr));
|
||||||
|
I := Result.IndexOf(' ');
|
||||||
|
if I >= 0 then
|
||||||
|
Result := Result.Substring(0, Result.IndexOf(' '));
|
||||||
|
end;
|
||||||
|
|
||||||
|
type
|
||||||
|
PCtx = ^TCtx;
|
||||||
|
|
||||||
|
TCtx = record
|
||||||
|
Exec, Param: String;
|
||||||
|
InFile, OutFile: String;
|
||||||
|
Mode: Byte;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Init(ParamArg: TArray<string>; Ctx: PCtx);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
S: String;
|
||||||
|
begin
|
||||||
|
with Ctx^ do
|
||||||
|
begin
|
||||||
|
Exec := '';
|
||||||
|
Param := '';
|
||||||
|
InFile := FILE_IN;
|
||||||
|
OutFile := FILE_OUT;
|
||||||
|
Mode := 0;
|
||||||
|
for I := Low(ParamArg) to High(ParamArg) do
|
||||||
|
begin
|
||||||
|
S := ParamArg[I];
|
||||||
|
if ContainsText(S, '<stdin>') or ContainsText(S, '[stdin]') then
|
||||||
|
begin
|
||||||
|
SetBits(Mode, 1, 0, 1);
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
else if ContainsText(S, '<stdout>') or ContainsText(S, '[stdout]') then
|
||||||
|
begin
|
||||||
|
SetBits(Mode, 1, 1, 1);
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
else if ContainsText(S, '<filein>') or ContainsText(S, '[filein]') then
|
||||||
|
begin
|
||||||
|
SetBits(Mode, 0, 0, 1);
|
||||||
|
if ContainsText(S, '<filein>') then
|
||||||
|
InFile := ExtractStr('<filein>', S)
|
||||||
|
else
|
||||||
|
InFile := ExtractStr('[filein]', S);
|
||||||
|
S := ReplaceText(S, InFile, FILE_IN);
|
||||||
|
InFile := ReplaceText(InFile, '<filein>', FILE_IN);
|
||||||
|
InFile := ReplaceText(InFile, '[filein]', FILE_IN);
|
||||||
|
end
|
||||||
|
else if ContainsText(S, '<fileout>') or ContainsText(S, '[fileout]') then
|
||||||
|
begin
|
||||||
|
SetBits(Mode, 0, 1, 1);
|
||||||
|
if ContainsText(S, '<fileout>') then
|
||||||
|
OutFile := ExtractStr('<fileout>', S)
|
||||||
|
else
|
||||||
|
OutFile := ExtractStr('[fileout]', S);
|
||||||
|
S := ReplaceText(S, OutFile, FILE_OUT);
|
||||||
|
OutFile := ReplaceText(OutFile, '<fileout>', FILE_OUT);
|
||||||
|
OutFile := ReplaceText(OutFile, '[fileout]', FILE_OUT);
|
||||||
|
end;
|
||||||
|
if I = 0 then
|
||||||
|
Exec := ExtractFilePath(Utils.GetModuleName) + S
|
||||||
|
else
|
||||||
|
Param := Param + ' ' + IfThen(ContainsText(S, ' ') or (S = ''),
|
||||||
|
'"' + S + '"', S);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
threadvar TFS: TFileStream;
|
||||||
|
|
||||||
|
procedure Callback(const Buffer: Pointer; Size: Integer);
|
||||||
|
begin
|
||||||
|
TFS.WriteBuffer(Buffer^, Size);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ExecThread(X, Ctx, WorkDir, State: IntPtr);
|
||||||
|
var
|
||||||
|
SS: TSharedMemoryStream;
|
||||||
|
Res: Boolean;
|
||||||
|
begin
|
||||||
|
Res := False;
|
||||||
|
with PCtx(Ctx)^ do
|
||||||
|
if FileExists(Exec) then
|
||||||
|
try
|
||||||
|
case Mode of
|
||||||
|
FILE_MODE:
|
||||||
|
Res := Utils.Exec(Exec, Param, PString(WorkDir)^);
|
||||||
|
STDIN_MODE:
|
||||||
|
begin
|
||||||
|
SS := TSharedMemoryStream.Create
|
||||||
|
(LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF2)),
|
||||||
|
IncludeTrailingBackSlash(PString(WorkDir)^) + InFile);
|
||||||
|
try
|
||||||
|
Res := ExecStdin(Exec, Param, PString(WorkDir)^,
|
||||||
|
SS.Memory, SS.Size);
|
||||||
|
finally
|
||||||
|
SS.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
STDOUT_MODE:
|
||||||
|
begin
|
||||||
|
TFS := TFileStream.Create
|
||||||
|
(IncludeTrailingBackSlash(PString(WorkDir)^) + OutFile,
|
||||||
|
fmCreate);
|
||||||
|
try
|
||||||
|
Res := ExecStdout(Exec, Param, PString(WorkDir)^, Callback);
|
||||||
|
finally
|
||||||
|
TFS.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
STDIO_MODE:
|
||||||
|
begin
|
||||||
|
SS := TSharedMemoryStream.Create
|
||||||
|
(LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF2)),
|
||||||
|
IncludeTrailingBackSlash(PString(WorkDir)^) + InFile);
|
||||||
|
TFS := TFileStream.Create
|
||||||
|
(IncludeTrailingBackSlash(PString(WorkDir)^) + OutFile,
|
||||||
|
fmCreate);
|
||||||
|
try
|
||||||
|
Res := ExecStdio(Exec, Param, PString(WorkDir)^, SS.Memory,
|
||||||
|
SS.Size, Callback);
|
||||||
|
finally
|
||||||
|
SS.Free;
|
||||||
|
TFS.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
except
|
||||||
|
Res := False
|
||||||
|
end;
|
||||||
|
if Res then
|
||||||
|
PByte(State)^ := STATE_EXECUTED
|
||||||
|
else
|
||||||
|
PByte(State)^ := STATE_ERROR;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Encode(Input, Output: TStream; ParamArg: TArray<string>;
|
||||||
|
Options: TEncodeOptions);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
I64: Int64;
|
||||||
|
B: Byte;
|
||||||
|
S: String;
|
||||||
|
First, Done: Boolean;
|
||||||
|
FStream: TFileStream;
|
||||||
|
SStream: TSharedMemoryStream;
|
||||||
|
LCtx: TCtx;
|
||||||
|
WorkDir: TArray<String>;
|
||||||
|
Tasks: TArray<TTask>;
|
||||||
|
State: TArray<Byte>;
|
||||||
|
|
||||||
|
procedure Load(X: Integer);
|
||||||
|
begin
|
||||||
|
DeleteFile(IncludeTrailingBackSlash(WorkDir[X]) + LCtx.InFile);
|
||||||
|
DeleteFile(IncludeTrailingBackSlash(WorkDir[X]) + LCtx.OutFile);
|
||||||
|
if not Done then
|
||||||
|
begin
|
||||||
|
FStream := TFileStream.Create(IncludeTrailingBackSlash(WorkDir[X]) +
|
||||||
|
LCtx.InFile, fmCreate);
|
||||||
|
try
|
||||||
|
Done := CopyStream(Input, FStream, Options.ChunkSize) = 0;
|
||||||
|
finally
|
||||||
|
FStream.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if Done then
|
||||||
|
State[X] := STATE_DONE
|
||||||
|
else
|
||||||
|
State[X] := STATE_READY;
|
||||||
|
if not Done then
|
||||||
|
Tasks[X].Start;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
I := XTOOL_EXEC;
|
||||||
|
Output.WriteBuffer(I, I.Size);
|
||||||
|
Init(ParamArg, @LCtx);
|
||||||
|
SetLength(WorkDir, Options.Threads);
|
||||||
|
SetLength(Tasks, Options.Threads);
|
||||||
|
SetLength(State, Options.Threads);
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
WorkDir[I] := IncludeTrailingBackSlash(GetCurrentDir) +
|
||||||
|
LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF1));
|
||||||
|
CreateDir(WorkDir[I]);
|
||||||
|
Tasks[I] := TTask.Create(I, IntPtr(@LCtx), IntPtr(@WorkDir[I]),
|
||||||
|
IntPtr(@State[I]));
|
||||||
|
Tasks[I].Perform(ExecThread);
|
||||||
|
end;
|
||||||
|
First := True;
|
||||||
|
Done := False;
|
||||||
|
try
|
||||||
|
while State[0] <> STATE_DONE do
|
||||||
|
begin
|
||||||
|
if First then
|
||||||
|
begin
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
Load(I);
|
||||||
|
First := False;
|
||||||
|
end;
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
Tasks[I].Wait;
|
||||||
|
if State[I] = STATE_DONE then
|
||||||
|
continue;
|
||||||
|
B := 0;
|
||||||
|
if State[I] = STATE_EXECUTED then
|
||||||
|
S := IncludeTrailingBackSlash(WorkDir[I]) + LCtx.OutFile
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
S := IncludeTrailingBackSlash(WorkDir[I]) + LCtx.InFile;
|
||||||
|
B := 1;
|
||||||
|
end;
|
||||||
|
SStream := TSharedMemoryStream.Create
|
||||||
|
(LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF2)), S);
|
||||||
|
try
|
||||||
|
Output.WriteBuffer(B, B.Size);
|
||||||
|
I64 := SStream.Size;
|
||||||
|
Output.WriteBuffer(I64, I64.Size);
|
||||||
|
CopyStreamEx(SStream, Output, SStream.Size);
|
||||||
|
finally
|
||||||
|
SStream.Free;
|
||||||
|
end;
|
||||||
|
Load(I);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
WaitForAll(Tasks);
|
||||||
|
B := 0;
|
||||||
|
Output.WriteBuffer(B, B.Size);
|
||||||
|
I64 := I64.MinValue;
|
||||||
|
Output.WriteBuffer(I64, I64.Size);
|
||||||
|
finally
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
if DirectoryExists(WorkDir[I]) then
|
||||||
|
TDirectory.Delete(WorkDir[I], True);
|
||||||
|
Tasks[I].Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Decode(Input, Output: TStream; ParamArg: TArray<string>;
|
||||||
|
Options: TDecodeOptions);
|
||||||
|
var
|
||||||
|
I: Integer;
|
||||||
|
S: String;
|
||||||
|
First, Done: Boolean;
|
||||||
|
FStream: TFileStream;
|
||||||
|
SStream: TSharedMemoryStream;
|
||||||
|
LCtx: TCtx;
|
||||||
|
WorkDir: TArray<String>;
|
||||||
|
Tasks: TArray<TTask>;
|
||||||
|
State: TArray<Byte>;
|
||||||
|
|
||||||
|
procedure Load(X: Integer);
|
||||||
|
var
|
||||||
|
B: Byte;
|
||||||
|
I64: Int64;
|
||||||
|
begin
|
||||||
|
DeleteFile(IncludeTrailingBackSlash(WorkDir[X]) + LCtx.InFile);
|
||||||
|
DeleteFile(IncludeTrailingBackSlash(WorkDir[X]) + LCtx.OutFile);
|
||||||
|
if not Done then
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
Input.ReadBuffer(B, B.Size);
|
||||||
|
Input.ReadBuffer(I64, I64.Size);
|
||||||
|
if I64 >= 0 then
|
||||||
|
begin
|
||||||
|
FStream := TFileStream.Create(IncludeTrailingBackSlash(WorkDir[X]) +
|
||||||
|
LCtx.InFile, fmCreate);
|
||||||
|
try
|
||||||
|
if B = 0 then
|
||||||
|
CopyStreamEx(Input, FStream, I64)
|
||||||
|
else
|
||||||
|
CopyStreamEx(Input, Output, I64);
|
||||||
|
finally
|
||||||
|
FStream.Free;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Done := True;
|
||||||
|
until (B = 0) or Done;
|
||||||
|
end;
|
||||||
|
if Done then
|
||||||
|
State[X] := STATE_DONE
|
||||||
|
else
|
||||||
|
State[X] := STATE_READY;
|
||||||
|
if not Done then
|
||||||
|
Tasks[X].Start;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Init(ParamArg, @LCtx);
|
||||||
|
SetLength(WorkDir, Options.Threads);
|
||||||
|
SetLength(Tasks, Options.Threads);
|
||||||
|
SetLength(State, Options.Threads);
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
WorkDir[I] := IncludeTrailingBackSlash(GetCurrentDir) +
|
||||||
|
LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF1));
|
||||||
|
CreateDir(WorkDir[I]);
|
||||||
|
Tasks[I] := TTask.Create(I, IntPtr(@LCtx), IntPtr(@WorkDir[I]),
|
||||||
|
IntPtr(@State[I]));
|
||||||
|
Tasks[I].Perform(ExecThread);
|
||||||
|
end;
|
||||||
|
First := True;
|
||||||
|
Done := False;
|
||||||
|
try
|
||||||
|
while State[0] <> STATE_DONE do
|
||||||
|
begin
|
||||||
|
if First then
|
||||||
|
begin
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
Load(I);
|
||||||
|
First := False;
|
||||||
|
end;
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
Tasks[I].Wait;
|
||||||
|
if State[I] = STATE_DONE then
|
||||||
|
continue;
|
||||||
|
if State[I] = STATE_EXECUTED then
|
||||||
|
S := IncludeTrailingBackSlash(WorkDir[I]) + LCtx.OutFile
|
||||||
|
else
|
||||||
|
raise Exception.CreateRes(@SWriteError);
|
||||||
|
SStream := TSharedMemoryStream.Create
|
||||||
|
(LowerCase(ChangeFileExt(ExtractFileName(Utils.GetModuleName),
|
||||||
|
'_' + Random($7FFFFFFF).ToHexString + XTOOL_MAPSUF2)), S);
|
||||||
|
try
|
||||||
|
CopyStreamEx(SStream, Output, SStream.Size);
|
||||||
|
finally
|
||||||
|
SStream.Free;
|
||||||
|
end;
|
||||||
|
Load(I);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
WaitForAll(Tasks);
|
||||||
|
finally
|
||||||
|
for I := Low(Tasks) to High(Tasks) do
|
||||||
|
begin
|
||||||
|
if DirectoryExists(WorkDir[I]) then
|
||||||
|
TDirectory.Delete(WorkDir[I], True);
|
||||||
|
Tasks[I].Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
|
@ -206,11 +206,12 @@ begin
|
||||||
SStream1.Free;
|
SStream1.Free;
|
||||||
SStream2.Free;
|
SStream2.Free;
|
||||||
end;
|
end;
|
||||||
if B then
|
if not B then
|
||||||
if InRange(FileSize(BaseDir2 + LList2[I]), Options.MinSize,
|
if InRange(FileSize(BaseDir2 + LList2[I]), Options.MinSize,
|
||||||
Options.MaxSize) then
|
Options.MaxSize) then
|
||||||
continue;
|
continue;
|
||||||
end;
|
end;
|
||||||
|
ShowMessage(LFilename);
|
||||||
LEntry.Op := TPatchOp.opMissing;
|
LEntry.Op := TPatchOp.opMissing;
|
||||||
LEntry.Filename := LList2[I];
|
LEntry.Filename := LList2[I];
|
||||||
LEntry.Size := FileSize(BaseDir2 + LList2[I]);
|
LEntry.Size := FileSize(BaseDir2 + LList2[I]);
|
||||||
|
@ -269,7 +270,7 @@ begin
|
||||||
try
|
try
|
||||||
SS0.Size := Max(SS1.Size, SS2.Size);
|
SS0.Size := Max(SS1.Size, SS2.Size);
|
||||||
A := xd3_encode(SS2.Memory, SS2.Size, SS1.Memory, SS1.Size,
|
A := xd3_encode(SS2.Memory, SS2.Size, SS1.Memory, SS1.Size,
|
||||||
SS0.Memory, @Res, SS0.Size, 0) = 0;
|
SS0.Memory, @Res, SS0.Size, Integer(XD3_NOCOMPRESS)) = 0;
|
||||||
if A then
|
if A then
|
||||||
SS0.Size := Res;
|
SS0.Size := Res;
|
||||||
finally
|
finally
|
||||||
|
@ -335,7 +336,7 @@ begin
|
||||||
Tasks[I].Free;
|
Tasks[I].Free;
|
||||||
CS.Free;
|
CS.Free;
|
||||||
if DirectoryExists(TempDir) then
|
if DirectoryExists(TempDir) then
|
||||||
TDirectory.Delete(TempDir);
|
TDirectory.Delete(TempDir, True);
|
||||||
end;
|
end;
|
||||||
FillChar(LEntry, SizeOf(TEntryStruct2), 0);
|
FillChar(LEntry, SizeOf(TEntryStruct2), 0);
|
||||||
LEntry.Op := TPatchOp.opNone;
|
LEntry.Op := TPatchOp.opNone;
|
||||||
|
@ -404,7 +405,8 @@ begin
|
||||||
try
|
try
|
||||||
SStream2.Size := LEntry.Size;
|
SStream2.Size := LEntry.Size;
|
||||||
B := xd3_decode(SStream0.Memory, I64, SStream1.Memory,
|
B := xd3_decode(SStream0.Memory, I64, SStream1.Memory,
|
||||||
SStream1.Size, SStream2.Memory, @Res, SStream2.Size, 0) = 0;
|
SStream1.Size, SStream2.Memory, @Res, SStream2.Size,
|
||||||
|
Integer(XD3_NOCOMPRESS)) = 0;
|
||||||
finally
|
finally
|
||||||
SStream1.Free;
|
SStream1.Free;
|
||||||
SStream2.Free;
|
SStream2.Free;
|
||||||
|
|
|
@ -10,6 +10,8 @@ uses
|
||||||
const
|
const
|
||||||
XTOOL_IODEC = $314C5458;
|
XTOOL_IODEC = $314C5458;
|
||||||
XTOOL_PATCH = $324C5458;
|
XTOOL_PATCH = $324C5458;
|
||||||
|
XTOOL_ARCH = $334C5458;
|
||||||
|
XTOOL_EXEC = $344C5458;
|
||||||
XTOOL_MAPSUF1 = '-tmp';
|
XTOOL_MAPSUF1 = '-tmp';
|
||||||
XTOOL_MAPSUF2 = '_mapped.io';
|
XTOOL_MAPSUF2 = '_mapped.io';
|
||||||
XTOOL_MAPSUF3 = '.tmp';
|
XTOOL_MAPSUF3 = '.tmp';
|
||||||
|
|
|
@ -725,12 +725,14 @@ begin
|
||||||
ExeStruct^.IsLib[X] := True;
|
ExeStruct^.IsLib[X] := True;
|
||||||
continue;
|
continue;
|
||||||
end
|
end
|
||||||
else if ContainsText(S2, '<stdin>') then
|
else if ContainsText(S2, '<stdin>') or ContainsText(S2, '[stdin]')
|
||||||
|
then
|
||||||
begin
|
begin
|
||||||
SetBits(ExeStruct^.Mode[X], 1, 0, 1);
|
SetBits(ExeStruct^.Mode[X], 1, 0, 1);
|
||||||
continue;
|
continue;
|
||||||
end
|
end
|
||||||
else if ContainsText(S2, '<stdout>') then
|
else if ContainsText(S2, '<stdout>') or ContainsText(S2, '[stdout]')
|
||||||
|
then
|
||||||
begin
|
begin
|
||||||
SetBits(ExeStruct^.Mode[X], 1, 1, 1);
|
SetBits(ExeStruct^.Mode[X], 1, 1, 1);
|
||||||
continue;
|
continue;
|
||||||
|
@ -741,19 +743,14 @@ begin
|
||||||
S3 := IfThen(X = 0, FILE_IN, FILE_OUT);
|
S3 := IfThen(X = 0, FILE_IN, FILE_OUT);
|
||||||
SetBits(ExeStruct^.Mode[X], 0, 0, 1);
|
SetBits(ExeStruct^.Mode[X], 0, 0, 1);
|
||||||
if ContainsText(S2, '<filein>') then
|
if ContainsText(S2, '<filein>') then
|
||||||
begin
|
ExeStruct^.InFile[X] := ExtractStr('<filein>', S2)
|
||||||
ExeStruct^.InFile[X] := ExtractStr('<filein>', S2);
|
|
||||||
S2 := ReplaceText(S2, ExeStruct^.InFile[X], S3);
|
|
||||||
ExeStruct^.InFile[X] := ReplaceText(ExeStruct^.InFile[X],
|
|
||||||
'<filein>', S3);
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
ExeStruct^.InFile[X] := ExtractStr('[filein]', S2);
|
ExeStruct^.InFile[X] := ExtractStr('[filein]', S2);
|
||||||
S2 := ReplaceText(S2, ExeStruct^.InFile[X], '');
|
S2 := ReplaceText(S2, ExeStruct^.InFile[X], S3);
|
||||||
ExeStruct^.InFile[X] := ReplaceText(ExeStruct^.InFile[X],
|
ExeStruct^.InFile[X] := ReplaceText(ExeStruct^.InFile[X],
|
||||||
'[filein]', S3);
|
'<filein>', S3);
|
||||||
end;
|
ExeStruct^.InFile[X] := ReplaceText(ExeStruct^.InFile[X],
|
||||||
|
'[filein]', S3);
|
||||||
end
|
end
|
||||||
else if ContainsText(S2, '<fileout>') or
|
else if ContainsText(S2, '<fileout>') or
|
||||||
ContainsText(S2, '[fileout]') then
|
ContainsText(S2, '[fileout]') then
|
||||||
|
@ -761,19 +758,14 @@ begin
|
||||||
S3 := IfThen(X = 0, FILE_OUT, FILE_IN);
|
S3 := IfThen(X = 0, FILE_OUT, FILE_IN);
|
||||||
SetBits(ExeStruct^.Mode[X], 0, 1, 1);
|
SetBits(ExeStruct^.Mode[X], 0, 1, 1);
|
||||||
if ContainsText(S2, '<fileout>') then
|
if ContainsText(S2, '<fileout>') then
|
||||||
begin
|
ExeStruct^.OutFile[X] := ExtractStr('<fileout>', S2)
|
||||||
ExeStruct^.OutFile[X] := ExtractStr('<fileout>', S2);
|
|
||||||
S2 := ReplaceText(S2, ExeStruct^.OutFile[X], S3);
|
|
||||||
ExeStruct^.OutFile[X] := ReplaceText(ExeStruct^.OutFile[X],
|
|
||||||
'<fileout>', S3);
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
ExeStruct^.OutFile[X] := ExtractStr('[fileout]', S2);
|
ExeStruct^.OutFile[X] := ExtractStr('[fileout]', S2);
|
||||||
S2 := ReplaceText(S2, ExeStruct^.OutFile[X], '');
|
S2 := ReplaceText(S2, ExeStruct^.OutFile[X], S3);
|
||||||
ExeStruct^.OutFile[X] := ReplaceText(ExeStruct^.OutFile[X],
|
ExeStruct^.OutFile[X] := ReplaceText(ExeStruct^.OutFile[X],
|
||||||
'[fileout]', S3);
|
'<fileout>', S3);
|
||||||
end;
|
ExeStruct^.OutFile[X] := ReplaceText(ExeStruct^.OutFile[X],
|
||||||
|
'[fileout]', S3);
|
||||||
end;
|
end;
|
||||||
S2 := IfThen((Pos(' ', S2) > 0) or (S2 = ''), '"' + S2 + '"', S2);
|
S2 := IfThen((Pos(' ', S2) > 0) or (S2 = ''), '"' + S2 + '"', S2);
|
||||||
ExeStruct^.Param[X] := ExeStruct^.Param[X] + ' ' + S2;
|
ExeStruct^.Param[X] := ExeStruct^.Param[X] + ' ' + S2;
|
||||||
|
|
180
xtool.dpr
180
xtool.dpr
|
@ -79,7 +79,9 @@ uses
|
||||||
IOFind in 'io\IOFind.pas',
|
IOFind in 'io\IOFind.pas',
|
||||||
IOErase in 'io\IOErase.pas',
|
IOErase in 'io\IOErase.pas',
|
||||||
IOReplace in 'io\IOReplace.pas',
|
IOReplace in 'io\IOReplace.pas',
|
||||||
|
IOArchive in 'io\IOArchive.pas',
|
||||||
IOPatch in 'io\IOPatch.pas',
|
IOPatch in 'io\IOPatch.pas',
|
||||||
|
IOExecute in 'io\IOExecute.pas',
|
||||||
IODecode in 'io\IODecode.pas',
|
IODecode in 'io\IODecode.pas',
|
||||||
IOUtils in 'io\IOUtils.pas';
|
IOUtils in 'io\IOUtils.pas';
|
||||||
|
|
||||||
|
@ -93,6 +95,8 @@ const
|
||||||
CommandReplace = 'replace';
|
CommandReplace = 'replace';
|
||||||
CommandExtract = 'extract';
|
CommandExtract = 'extract';
|
||||||
CommandPatch = 'patch';
|
CommandPatch = 'patch';
|
||||||
|
CommandArchive = 'archive';
|
||||||
|
CommandExecute = 'execute';
|
||||||
CommandDecode = 'decode';
|
CommandDecode = 'decode';
|
||||||
|
|
||||||
procedure ProgramInfo;
|
procedure ProgramInfo;
|
||||||
|
@ -106,7 +110,9 @@ begin
|
||||||
WriteLine('Available commands:');
|
WriteLine('Available commands:');
|
||||||
WriteLine('');
|
WriteLine('');
|
||||||
WriteLine(' ' + CommandDecode);
|
WriteLine(' ' + CommandDecode);
|
||||||
|
WriteLine(' ' + CommandArchive);
|
||||||
WriteLine(' ' + CommandErase);
|
WriteLine(' ' + CommandErase);
|
||||||
|
WriteLine(' ' + CommandExecute);
|
||||||
WriteLine(' ' + CommandExtract);
|
WriteLine(' ' + CommandExtract);
|
||||||
WriteLine(' ' + CommandFind);
|
WriteLine(' ' + CommandFind);
|
||||||
WriteLine(' ' + CommandGenerate);
|
WriteLine(' ' + CommandGenerate);
|
||||||
|
@ -149,6 +155,11 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ changelog
|
{ changelog
|
||||||
|
ES_R33 (0.5.2)
|
||||||
|
- added IO functions (archive, execute)
|
||||||
|
- fixed issue in patch io function
|
||||||
|
- removed compression on patch diff files
|
||||||
|
|
||||||
ES_R32 (0.5.1)
|
ES_R32 (0.5.1)
|
||||||
- added IO functions (find, extract, patch)
|
- added IO functions (find, extract, patch)
|
||||||
- generate database feature and IO functions now can search for streams larger than chunk size
|
- generate database feature and IO functions now can search for streams larger than chunk size
|
||||||
|
@ -387,6 +398,7 @@ const
|
||||||
var
|
var
|
||||||
I, J: Integer;
|
I, J: Integer;
|
||||||
ParamArg: array [0 .. 1] of TArray<String>;
|
ParamArg: array [0 .. 1] of TArray<String>;
|
||||||
|
StrArray: TArray<String>;
|
||||||
IsParam: Boolean;
|
IsParam: Boolean;
|
||||||
Input, Output: TStream;
|
Input, Output: TStream;
|
||||||
PrecompEnc: PrecompMain.TEncodeOptions;
|
PrecompEnc: PrecompMain.TEncodeOptions;
|
||||||
|
@ -397,6 +409,10 @@ var
|
||||||
ReplaceEnc: IOReplace.TEncodeOptions;
|
ReplaceEnc: IOReplace.TEncodeOptions;
|
||||||
PatchEnc: IOPatch.TEncodeOptions;
|
PatchEnc: IOPatch.TEncodeOptions;
|
||||||
PatchDec: IOPatch.TDecodeOptions;
|
PatchDec: IOPatch.TDecodeOptions;
|
||||||
|
ArchiveEnc: IOArchive.TEncodeOptions;
|
||||||
|
ArchiveDec: IOArchive.TDecodeOptions;
|
||||||
|
ExecuteEnc: IOExecute.TEncodeOptions;
|
||||||
|
ExecuteDec: IOExecute.TDecodeOptions;
|
||||||
IODec: IODecode.TDecodeOptions;
|
IODec: IODecode.TDecodeOptions;
|
||||||
IOExt: IODecode.TExtractOptions;
|
IOExt: IODecode.TExtractOptions;
|
||||||
|
|
||||||
|
@ -438,14 +454,17 @@ begin
|
||||||
begin
|
begin
|
||||||
while Length(ParamArg[1]) < 2 do
|
while Length(ParamArg[1]) < 2 do
|
||||||
Insert('-', ParamArg[1], Length(ParamArg[1]));
|
Insert('-', ParamArg[1], Length(ParamArg[1]));
|
||||||
Input := TBufferedStream.Create(GetInStream(ParamArg[1][0]), True,
|
Input := TBufferedStream.Create(GetInStream(ParamArg[1, 0]), True,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
Output := TBufferedStream.Create(GetOutStream(ParamArg[1][1]), False,
|
Output := TBufferedStream.Create(GetOutStream(ParamArg[1, 1]), False,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
PrecompMain.Parse(ParamArg[0], PrecompEnc);
|
try
|
||||||
PrecompMain.Encode(Input, Output, PrecompEnc);
|
PrecompMain.Parse(ParamArg[0], PrecompEnc);
|
||||||
Input.Free;
|
PrecompMain.Encode(Input, Output, PrecompEnc);
|
||||||
Output.Free;
|
finally
|
||||||
|
Input.Free;
|
||||||
|
Output.Free;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandGenerate, True) then
|
if ParamStr(1).StartsWith(CommandGenerate, True) then
|
||||||
if Length(ParamArg[1]) < 3 then
|
if Length(ParamArg[1]) < 3 then
|
||||||
|
@ -453,7 +472,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
DbgMain.Parse(ParamArg[0], GenerateEnc);
|
DbgMain.Parse(ParamArg[0], GenerateEnc);
|
||||||
DbgMain.Encode(ParamArg[1][0], ParamArg[1][1], ParamArg[1][2],
|
DbgMain.Encode(ParamArg[1, 0], ParamArg[1, 1], ParamArg[1, 2],
|
||||||
GenerateEnc);
|
GenerateEnc);
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandFind, True) then
|
if ParamStr(1).StartsWith(CommandFind, True) then
|
||||||
|
@ -462,7 +481,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
IOFind.Parse(ParamArg[0], FindEnc);
|
IOFind.Parse(ParamArg[0], FindEnc);
|
||||||
IOFind.Encode(ParamArg[1][0], ParamArg[1][1],
|
IOFind.Encode(ParamArg[1, 0], ParamArg[1, 1],
|
||||||
ParamArgSafe(1, 2), FindEnc);
|
ParamArgSafe(1, 2), FindEnc);
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandErase, True) then
|
if ParamStr(1).StartsWith(CommandErase, True) then
|
||||||
|
@ -471,7 +490,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
IOErase.Parse(ParamArg[0], EraseEnc);
|
IOErase.Parse(ParamArg[0], EraseEnc);
|
||||||
IOErase.Encode(ParamArg[1][0], ParamArg[1][1], ParamArgSafe(1, 2),
|
IOErase.Encode(ParamArg[1, 0], ParamArg[1, 1], ParamArgSafe(1, 2),
|
||||||
EraseEnc);
|
EraseEnc);
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandReplace, True) then
|
if ParamStr(1).StartsWith(CommandReplace, True) then
|
||||||
|
@ -480,7 +499,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
IOReplace.Parse(ParamArg[0], ReplaceEnc);
|
IOReplace.Parse(ParamArg[0], ReplaceEnc);
|
||||||
IOReplace.Encode(ParamArg[1][0], ParamArg[1][1], ParamArg[1][2],
|
IOReplace.Encode(ParamArg[1, 0], ParamArg[1, 1], ParamArg[1, 2],
|
||||||
ParamArgSafe(1, 3), ReplaceEnc);
|
ParamArgSafe(1, 3), ReplaceEnc);
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandExtract, True) then
|
if ParamStr(1).StartsWith(CommandExtract, True) then
|
||||||
|
@ -490,28 +509,74 @@ begin
|
||||||
begin
|
begin
|
||||||
Input := TBufferedStream.Create(GetInStream(ParamArgSafe(1, 0)), True,
|
Input := TBufferedStream.Create(GetInStream(ParamArgSafe(1, 0)), True,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
Input.ReadBuffer(I, I.Size);
|
try
|
||||||
case I of
|
Input.ReadBuffer(I, I.Size);
|
||||||
XTOOL_IODEC:
|
case I of
|
||||||
begin
|
XTOOL_IODEC:
|
||||||
IODecode.ParseExtract(ParamArg[0], IOExt);
|
begin
|
||||||
IODecode.Extract(Input, ParamArgSafe(1, 1),
|
IODecode.ParseExtract(ParamArg[0], IOExt);
|
||||||
ParamArgSafe(1, 2), IOExt);
|
IODecode.Extract(Input, ParamArgSafe(1, 1),
|
||||||
end;
|
ParamArgSafe(1, 2), IOExt);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Input.Free;
|
||||||
end;
|
end;
|
||||||
Input.Free;
|
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandPatch, True) then
|
if ParamStr(1).StartsWith(CommandPatch, True) then
|
||||||
if Length(ParamArg[1]) < 3 then
|
if Length(ParamArg[1]) < 3 then
|
||||||
IOPatch.PrintHelp
|
IOPatch.PrintHelp
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
Output := TBufferedStream.Create(GetOutStream(ParamArg[1][2]), False,
|
Output := TBufferedStream.Create(GetOutStream(ParamArg[1, 2]), False,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
IOPatch.Parse(ParamArg[0], PatchEnc);
|
try
|
||||||
IOPatch.Encode(ParamArg[1][0], ParamArg[1][1], Output, PatchEnc);
|
IOPatch.Parse(ParamArg[0], PatchEnc);
|
||||||
Input.Free;
|
IOPatch.Encode(ParamArg[1, 0], ParamArg[1, 1], Output, PatchEnc);
|
||||||
Output.Free;
|
finally
|
||||||
|
Output.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if ParamStr(1).StartsWith(CommandArchive, True) then
|
||||||
|
if (Length(ParamArg[0]) = 0) and (Length(ParamArg[1]) = 0) then
|
||||||
|
IOArchive.PrintHelp
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
while Length(ParamArg[1]) < 2 do
|
||||||
|
Insert('-', ParamArg[1], Length(ParamArg[1]));
|
||||||
|
SetLength(StrArray, 0);
|
||||||
|
for I := 0 to High(ParamArg[1]) - 1 do
|
||||||
|
Insert(ParamArg[1, I], StrArray, Length(StrArray));
|
||||||
|
Output := TBufferedStream.Create
|
||||||
|
(GetOutStream(ParamArg[1, High(ParamArg[1])]), False, BufferSize);
|
||||||
|
try
|
||||||
|
IOArchive.Parse(ParamArg[0], ArchiveEnc);
|
||||||
|
IOArchive.Encode(StrArray, Output, ArchiveEnc);
|
||||||
|
finally
|
||||||
|
Input.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if ParamStr(1).StartsWith(CommandExecute, True) then
|
||||||
|
if (Length(ParamArg[0]) = 0) and (Length(ParamArg[1]) = 0) then
|
||||||
|
IOExecute.PrintHelp
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
while Length(ParamArg[1]) < 2 do
|
||||||
|
Insert('-', ParamArg[1], Length(ParamArg[1]));
|
||||||
|
SetLength(StrArray, 0);
|
||||||
|
for I := 2 to High(ParamArg[1]) do
|
||||||
|
Insert(ParamArg[1, I], StrArray, Length(StrArray));
|
||||||
|
Input := TBufferedStream.Create(GetInStream(ParamArg[1, 0]), True,
|
||||||
|
BufferSize);
|
||||||
|
Output := TBufferedStream.Create(GetOutStream(ParamArg[1, 1]), False,
|
||||||
|
BufferSize);
|
||||||
|
try
|
||||||
|
IOExecute.Parse(ParamArg[0], ExecuteEnc);
|
||||||
|
IOExecute.Encode(Input, Output, StrArray, ExecuteEnc);
|
||||||
|
finally
|
||||||
|
Input.Free;
|
||||||
|
Output.Free;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
if ParamStr(1).StartsWith(CommandDecode, True) then
|
if ParamStr(1).StartsWith(CommandDecode, True) then
|
||||||
if (Length(ParamArg[0]) = 0) and (Length(ParamArg[1]) = 0) then
|
if (Length(ParamArg[0]) = 0) and (Length(ParamArg[1]) = 0) then
|
||||||
|
@ -520,28 +585,53 @@ begin
|
||||||
begin
|
begin
|
||||||
Input := TBufferedStream.Create(GetInStream(ParamArgSafe(1, 0)), True,
|
Input := TBufferedStream.Create(GetInStream(ParamArgSafe(1, 0)), True,
|
||||||
BufferSize);
|
BufferSize);
|
||||||
Input.ReadBuffer(I, I.Size);
|
try
|
||||||
case I of
|
Input.ReadBuffer(I, I.Size);
|
||||||
XTOOL_PRECOMP:
|
case I of
|
||||||
begin
|
XTOOL_PRECOMP:
|
||||||
Output := TBufferedStream.Create(GetOutStream(ParamArgSafe(1, 1)),
|
begin
|
||||||
False, BufferSize);
|
Output := TBufferedStream.Create(GetOutStream(ParamArgSafe(1, 1)
|
||||||
PrecompMain.Parse(ParamArg[0], PrecompDec);
|
), False, BufferSize);
|
||||||
PrecompMain.Decode(Input, Output, PrecompDec);
|
try
|
||||||
Output.Free;
|
PrecompMain.Parse(ParamArg[0], PrecompDec);
|
||||||
end;
|
PrecompMain.Decode(Input, Output, PrecompDec);
|
||||||
XTOOL_IODEC:
|
finally
|
||||||
begin
|
Output.Free;
|
||||||
IODecode.ParseDecode(ParamArg[0], IODec);
|
end;
|
||||||
IODecode.Decode(Input, ParamArg[1][1], ParamArg[1][2], IODec);
|
end;
|
||||||
end;
|
XTOOL_IODEC:
|
||||||
XTOOL_PATCH:
|
begin
|
||||||
begin
|
IODecode.ParseDecode(ParamArg[0], IODec);
|
||||||
IOPatch.Parse(ParamArg[0], PatchDec);
|
IODecode.Decode(Input, ParamArg[1, 1], ParamArg[1, 2], IODec);
|
||||||
IOPatch.Decode(Input, ParamArg[1][1], PatchDec);
|
end;
|
||||||
end;
|
XTOOL_PATCH:
|
||||||
|
begin
|
||||||
|
IOPatch.Parse(ParamArg[0], PatchDec);
|
||||||
|
IOPatch.Decode(Input, ParamArg[1, 1], PatchDec);
|
||||||
|
end;
|
||||||
|
XTOOL_ARCH:
|
||||||
|
begin
|
||||||
|
IOArchive.Parse(ParamArg[0], ArchiveDec);
|
||||||
|
IOArchive.Decode(Input, ParamArg[1, 1], ArchiveDec);
|
||||||
|
end;
|
||||||
|
XTOOL_EXEC:
|
||||||
|
begin
|
||||||
|
SetLength(StrArray, 0);
|
||||||
|
for I := 2 to High(ParamArg[1]) do
|
||||||
|
Insert(ParamArg[1, I], StrArray, Length(StrArray));
|
||||||
|
Output := TBufferedStream.Create(GetOutStream(ParamArgSafe(1, 1)
|
||||||
|
), False, BufferSize);
|
||||||
|
try
|
||||||
|
IOExecute.Parse(ParamArg[0], ExecuteDec);
|
||||||
|
IOExecute.Decode(Input, Output, StrArray, ExecuteDec);
|
||||||
|
finally
|
||||||
|
Output.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Input.Free;
|
||||||
end;
|
end;
|
||||||
Input.Free;
|
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
on E: Exception do
|
on E: Exception do
|
||||||
|
|
|
@ -138,7 +138,9 @@
|
||||||
<DCCReference Include="io\IOFind.pas"/>
|
<DCCReference Include="io\IOFind.pas"/>
|
||||||
<DCCReference Include="io\IOErase.pas"/>
|
<DCCReference Include="io\IOErase.pas"/>
|
||||||
<DCCReference Include="io\IOReplace.pas"/>
|
<DCCReference Include="io\IOReplace.pas"/>
|
||||||
|
<DCCReference Include="io\IOArchive.pas"/>
|
||||||
<DCCReference Include="io\IOPatch.pas"/>
|
<DCCReference Include="io\IOPatch.pas"/>
|
||||||
|
<DCCReference Include="io\IOExecute.pas"/>
|
||||||
<DCCReference Include="io\IODecode.pas"/>
|
<DCCReference Include="io\IODecode.pas"/>
|
||||||
<DCCReference Include="io\IOUtils.pas"/>
|
<DCCReference Include="io\IOUtils.pas"/>
|
||||||
<RcItem Include="resources\Win32\xdelta3_dll.dll">
|
<RcItem Include="resources\Win32\xdelta3_dll.dll">
|
||||||
|
|
Loading…
Reference in New Issue