+97
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
{$APPTYPE CONSOLE} {$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
uses SysUtils, Classes, IniFiles, Variants;
type TGetToken = function(var p: pointer): LongInt;
procedure ParseData(var p: pointer; isKey: boolean); forward;
procedure AdvanceIndex(var i: LongInt); forward;
function GetIntegerToken(var p: pointer): LongInt;
var value: LongInt = 0;
negative: boolean;
begin
Inc(p);
negative := PByte(p)^ = ord('-');
if negative then Inc(p);
repeat
value := value * 10 + LongInt(PByte(p)^ - $30);
Inc(p)
until PChar(p)^ = 'e';
Inc(p);
if negative then value := - value;
Result := value
end;
function GetListToken(var p: pointer): LongInt;
var index: Integer = 0;
begin
Inc(p);
while PChar(p)^ <> 'e' do begin
AdvanceIndex(index);
ParseData(p, false);
end;
Inc(p);
Result := -1
end;
function GetDictToken(var p: pointer): LongInt;
begin
Inc(p);
while PChar(p)^ <> 'e' do begin
ParseData(p, true);
ParseData(p, false);
end;
Inc(p);
Result := -1
end;
function ParseError(var p: pointer): LongInt;
begin
Writeln('TYIIINTE CBET');
Result := -1;
Halt(Result)
end;
const FuncTable: array[0..3] of TGetToken = (ParseError, GetDictToken, GetIntegerToken, GetListToken);
function GetStringToken(var p: pointer): string;
var value: ShortString;
length: LongInt = 0;
begin
repeat
length := length * 10 + LongInt(PByte(p)^ - $30);
Inc(p)
until PChar(p)^ = ':';
if length in [1..255] then begin
PByte(p)^ := length;
Move(p^, value, length+1);
Result := value;
end else Result := 'BINARY DATA';
Inc(p, length + 1);
end;
var sl: TStringList;
outf: TIniFile;
procedure AdvanceIndex(var i: LongInt);
begin
sl.Add(IntToStr(i));
Inc(i);
end;
type TSaveData = procedure(value: Variant);
procedure SaveData(value: Variant);
var
key: string = '';
i: LongInt;
begin
for i := 0 to sl.Count - 1 do key := key + '.' + sl[i];
Delete(key, 1, 1);
outf.WriteString('Torrent', key, VarToStr(value));
if sl.Count > 0 then sl.Delete(sl.Count - 1);
end;
procedure PushKey(value: Variant);
begin
sl.Add(value)
end;
procedure PopKey(value: Variant);
begin
if sl.Count > 0 then sl.Delete(sl.Count - 1);
end;
procedure NOP(value: Variant);
begin
end;
const SaveDataTable: array[0..3] of TSaveData = (SaveData, PushKey, PopKey, NOP);
procedure ParseData(var p: pointer; isKey: boolean);
var
OpCode: ShortInt;
value: Variant;
begin
OpCode := PByte(p)^;
if OpCode >= $60 then value := FuncTable[OpCode shr 2 and 3](p)
else if Opcode in [$30..$39] then value := GetStringToken(p)
else ParseError(p);
SaveDataTable[ord(isKey) + 2*ord(chr(OpCode) in ['d', 'l'])](value);
end;
var f: TFileStream;
s: LongInt;
p, cp: pointer;
begin
if ParamCount <> 1 then Writeln('Usage: ', ParamStr(0), ' filename.torrent')
else
try
f := TFileStream.Create(ParamStr(1), fmOpenRead);
s:= f.Size;
GetMem(p, s + 1);
f.ReadBuffer(p^, s);
cp := p;
outf := TIniFile.Create(ChangeFileExt(ParamStr(1), '.ini'));
sl := TStringList.Create;
ParseData(cp, false);
finally
if sl <> nil then sl.Destroy();
if outf <> nil then outf.Destroy();
if p <> nil then FreeMem(p);
if f <> nil then f.Destroy()
end
end.
Парсер torrent-файлов и сохранялка в INI-файл (пока без сумм фрагментов). Опа-лаба-стайл, писано левой ногой анскильного питуха.
Запостил: inkanus-gray,
09 Июля 2013
an0nym 09.07.2013 04:18 # +11
anonimb84a2f6fd141 09.07.2013 04:39 # +4
bee-squid 09.07.2013 08:42 # +3
Stertor 09.07.2013 09:33 # −10
Stertor 09.07.2013 09:38 # −13
Минуисуя участников, ты помогаешш обществу снижать ЧСВ.
absolut 09.07.2013 13:14 # +4
inkanus-gray 09.07.2013 14:35 # −3
1. В целях никому не нужной оптимизации была произведена никому не нужная байтомагия, поэтому некоторые ошибки синтаксиса будут проигнорированы. Так, например, неправильный код 'f' будет интерпретирован так же, как и код 'd'.
2. Генерация ключа в SaveData будет тормозить, потому что каждый раз пробегают весь цикл только питухи.
3. TIniFile — оверинженеринг. В данном контексте хватило бы и обычного printf WriteLn.
4. Рекурсия — говно. Пацан бы написал глобальный цикл и свой ручной стек.
5. Совмещают в одном коде парсер и анпарсер, минуя AST, только неосиляторы.
Dixi. Зато у меня нет свича на 200 строк.
Stertor 09.07.2013 15:44 # −2
kipar 10.07.2013 23:43 # +1
if sl <> nil then sl.Destroy();
if outf <> nil then outf.Destroy();
вместо sl.Free;outf.Free;
Stertor 11.07.2013 11:51 # 0
sl.Free;outf.Free;
а если так
правда, на Делфи:
kipar 11.07.2013 15:47 # 0
Stertor 11.07.2013 16:55 # 0
Stertor 26.07.2013 20:38 # −1
guest 09.07.2013 15:51 # 0
LXxhELT 25.08.2021 06:10 # 0