基本信息
源码名称:bt种子文件解析 含源码下载
源码大小:0.15M
文件格式:.zip
开发语言:Python
更新时间:2013-10-21
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
{BTTorrent B编码(Bencoding)格式分析} unit DxBencoding; interface uses Classes,SysUtils,Generics.Collections; type (* Torrent文件格式 Multi-file Torrent 多文件 ├─announce ├─announce-list ├─comment ├─comment.utf-8 ├─creation date ├─encoding ├─info │ ├─files │ │ ├─length │ │ ├─path │ │ └─path.utf-8 │ ├─name │ ├─name.utf-8 │ ├─piece length │ ├─pieces │ ├─publisher │ ├─publisher-url │ ├─publisher-url.utf-8 │ └─publisher.utf-8 └─nodes Single-File Torrent 单文件 ├─announce ├─announce-list ├─comment ├─comment.utf-8 ├─creation date ├─encoding ├─info │ ├─length │ ├─name │ ├─name.utf-8 │ ├─piece length │ ├─pieces │ ├─publisher │ ├─publisher-url │ ├─publisher-url.utf-8 │ └─publisher.utf-8 └─nodes *) //B编码支持的数据类型 TDxBenValueTypes = (DBV_String,DBV_Int,DBV_List,DBV_Dictionary); //B编码的节点,类似于JSON节点, TDxBenValue = class private FParent: TDxBenValue; protected function GetType:TDxBenValueTypes; virtual; abstract; procedure Parser(str: string);virtual;abstract; function GetAsInteger: Integer;virtual;abstract; function GetAsString: string;virtual;abstract; function GetObject: TDxBenValue;virtual; public constructor Create;overload;virtual; constructor Create(str: string);overload;virtual; property ValueType: TDxBenValueTypes read GetType; function ToString: string;override; property Parent: TDxBenValue read FParent; property AsInteger: Integer read GetAsInteger; property AsString: string read GetAsString; property AsValueObject: TDxBenValue read GetObject; end; TDxBenInt = class(TDxBenValue) private FValue: Integer; protected function GetType:TDxBenValueTypes;override; function GetAsInteger: Integer;override; procedure Parser(str: string);override; function GetAsString: string;override; function GetObject: TDxBenValue;override; public constructor Create;override; function ToString: string;override; end; TDxBenString = class(TDxBenValue) private FValue: string; protected function GetType:TDxBenValueTypes;override; function GetAsString: string;override; function GetObject: TDxBenValue;override; function GetAsInteger: Integer;override; procedure Parser(str: string);override; public function ToString: string;override; end; TDxBenDictionary = class; TDxBenList = class(TDxBenValue) private FList: TList; function GetCount: Integer; function GetValues(index: Integer): TDxBenValue; protected procedure Parser(str: string);override; procedure ParserToList(var P: Pchar;List: TDxBenList); procedure ParserToDictionary(var p: PChar;Dict: TDxBenDictionary); function GetType:TDxBenValueTypes;override; function GetAsString: string;override; function GetObject: TDxBenValue;override; function GetAsInteger: Integer;override; public procedure Clear; constructor Create; override; constructor CreateFromString(str: string); destructor Destroy;override; function ToString: string;override; property Count: Integer read GetCount; property Values[index: Integer]: TDxBenValue read GetValues; end; TDxBenDictionary = class(TDxBenValue) private FDict: TDictionary<string,TDxBenValue>; function GetCount: Integer; function GetValues(Key: string): TDxBenValue; protected procedure ParserToList(var P: Pchar;List: TDxBenList); procedure ParserToDictionary(var p: PChar;Dict: TDxBenDictionary); procedure Parser(str: string);override; function GetType:TDxBenValueTypes;override; function GetAsString: string;override; function GetObject: TDxBenValue;override; function GetAsInteger: Integer;override; public procedure Clear; constructor Create;override; destructor Destroy;override; function ToString: string;override; property Count: Integer read GetCount; property Values[Key: string]: TDxBenValue read GetValues; end; TDxBtInfo = class(TDxBenDictionary) private function GetSingleFile: Boolean; function GetFiles: TDxBenList; function GetName: string; function GetNameUtf8: string; function Getpublisher: string; function GetpublisherUtf8: string; function Getpublisherurl: string; function GetpublisherurlUtf8: string; public property SingleFile: Boolean read GetSingleFile; property Files: TDxBenList read GetFiles; property Name: string read GetName; property NameUtf8: string read GetNameUtf8; property publisher: string read Getpublisher; property publisherUtf8: string read GetpublisherUtf8; property publisherurl: string read Getpublisherurl; property publisherurlUtf8: string read GetpublisherurlUtf8; end; TDxTorrentFile = class private FDict: TDxBenDictionary; procedure ParserStream(Stream: TStream;Dict: TDxBenDictionary);overload; procedure ParserStreamToList(Stream: TStream; List: TDxBenList); function GetComment: string; function GetEncoding: string; function GetCreator: string; function Getannounce: string; function Getannounce_list: TDxBenList; function GetBtInfo: TDxBtInfo; function GetCreateDate: TDateTime; public procedure Clear; constructor Create; destructor Destroy;override; procedure LoadFromFile(FileName: string); procedure LoadFromStream(Stream: TStream); property Comment: string read GetComment; property Encoding: string read GetEncoding; property Creator: string read GetCreator; property announce: string read Getannounce; property announce_list: TDxBenList read Getannounce_list; property BtInfo: TDxBtInfo read GetBtInfo; property CreateDate: TDateTime read GetCreateDate; end; implementation { TDxBenValue } constructor TDxBenValue.Create; begin FParent := nil; end; constructor TDxBenValue.Create(str: string); begin Create; Parser(str); end; function TDxBenValue.GetObject: TDxBenValue; begin Result := Self; end; function TDxBenValue.ToString: string; begin Result := ''; end; { TDxBenInt } constructor TDxBenInt.Create; begin inherited; FValue := 0; end; function TDxBenInt.GetAsInteger: Integer; begin Result := FValue; end; function TDxBenInt.GetAsString: string; begin Result := IntToStr(FValue); end; function TDxBenInt.GetObject: TDxBenValue; begin Result := Self; end; function TDxBenInt.GetType: TDxBenValueTypes; begin Result := DBV_Int; end; procedure TDxBenInt.Parser(str: string); var len: Integer; begin len := Length(str); if (UpperCase(str[1]) = 'I') and (UpperCase(str[len]) = 'E') then begin Str := Copy(str,2,len - 2); if not TryStrToInt(str,FValue) then raise Exception.Create('无效的B编码整数格式'); end else raise Exception.Create('无效的B编码整数格式'); end; function TDxBenInt.ToString: string; begin Result := 'i' inttostr(FValue) 'e'; end; { TDxBenString } function TDxBenString.GetAsInteger: Integer; begin raise Exception.Create('字符串类型数据'); end; function TDxBenString.GetAsString: string; begin Result := FValue; end; function TDxBenString.GetObject: TDxBenValue; begin Result := Self; end; function TDxBenString.GetType: TDxBenValueTypes; begin Result := DBV_String; end; procedure TDxBenString.Parser(str: string); var ipos: Integer; str1: string; begin FValue := ''; ipos := Pos(':',str); if ipos <= 1 then raise Exception.Create('无效的数据格式') else begin str1 := Copy(str,1,ipos - 1); if not TryStrToInt(str1,ipos) then raise Exception.Create('无效的数据格式'); FValue := Copy(str,ipos 1,ipos); end; end; function TDxBenString.ToString: string; var len: Integer; begin len := Length(FValue); if len > 0 then Result := IntToStr(len) ':' FValue else Result := ''; end; { TDxBenList } procedure TDxBenList.Clear; begin while FList.Count > 0 do begin TDxBenValue(FList[FList.Count - 1]).Free; FList.Delete(FList.Count - 1); end; end; constructor TDxBenList.Create; begin inherited; FList := TList.Create; end; constructor TDxBenList.CreateFromString(str: string); begin Create; Parser(str); end; destructor TDxBenList.Destroy; begin Clear; FList.Free; inherited; end; function TDxBenList.GetAsInteger: Integer; begin raise Exception.Create('列表不支持'); end; function TDxBenList.GetAsString: string; begin raise Exception.Create('列表不支持'); end; function TDxBenList.GetCount: Integer; begin Result := FList.Count; end; function TDxBenList.GetObject: TDxBenValue; begin Result := inherited; end; function TDxBenList.GetType: TDxBenValueTypes; begin Result := DBV_List; end; function TDxBenList.GetValues(index: Integer): TDxBenValue; begin if index in [0..FList.Count-1] then Result := FList[index] else Result := nil; end; procedure TDxBenList.Parser(str: string); var len: Integer; p: PChar; begin len := Length(str); Clear; if (UpperCase(str[1]) = 'L') and (UpperCase(str[len]) = 'E') then begin Str := Copy(str,2,len - 2); p := @str[1]; ParserToList(p,nil); end else raise Exception.Create('无效的B编码列表格式'); end; procedure TDxBenList.ParserToDictionary(var p: PChar; Dict: TDxBenDictionary); type TParserState = (PS_None,PS_Key,PS_Value); var t: Char; st: string; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; Parstate: TParserState; key: string; begin //开始解析 Parstate := PS_None; while p^ <> '' do begin t := P^; case t of 'i': begin //整数 if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); st := ''; while p^ <> 'e' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; IntValue.FParent := Dict; Dict.FDict[Key] := IntValue; Inc(p); end; 'l': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); ListValue := TDxBenList.Create; ListValue.FParent := Dict; Dict.FDict[Key] := ListValue; ParserToList(p,ListValue); end; 'd': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); DicValue := TDxBenDictionary.Create; DicValue.FParent := Dict; Dict.FDict[Key] := DicValue; ParserToDictionary(p,DicValue); end; 'e': begin if Parstate = PS_Value then Parstate := PS_None else if Parstate = PS_None then Break; end; else begin st := ''; while p^ <> ':' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); //读取字符串 Inc(p); if StrLen(p) < FInt then raise Exception.Create('字符串解析长度不够'); SetLength(st,Fint); Move(p^,Pointer(St)^,FInt*Sizeof(Char)); Inc(p,Fint); if Parstate = PS_None then begin key := st; if Dict.FDict.ContainsKey(st) then raise Exception.Create('字典存在重复信息'); Dict.FDict.Add(st,nil); Parstate := PS_Value; end else if Parstate = PS_Value then begin StrValue := TDxBenString.Create; StrValue.FParent := Dict; StrValue.FValue := st; Dict.FDict[Key] := StrValue; end; end; end; end; end; procedure TDxBenList.ParserToList(var P: PChar; List: TDxBenList); var t: Char; st: string; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; begin //开始解析 while p^ <> '' do begin t := P^; case t of 'i': begin //是一个整数 Inc(p); st := ''; while p^ <> 'e' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; if List = nil then begin IntValue.FParent := Self; FList.Add(IntValue); end else begin IntValue.FParent := List; List.FList.Add(IntValue) end; Inc(p); end; 'l': begin //列表 Inc(p); ListValue := TDxBenList.Create; if List = nil then begin ListValue.FParent := Self; FList.Add(ListValue); end else begin ListValue.FParent := List; List.FList.Add(ListValue) end; ParserToList(p,ListValue); end; 'd': begin //字典 Inc(p); DicValue := TDxBenDictionary.Create; if List = nil then begin DicValue.FParent := Self; FList.Add(DicValue); end else begin DicValue.FParent := List; List.FList.Add(DicValue) end; ParserToDictionary(p,DicValue); end; 'e': Break;//结束了 else begin //字符串 st := ''; while p^ <> ':' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); //读取字符串 Inc(p); if StrLen(p) < FInt then raise Exception.Create('字符串解析长度不够'); StrValue := TDxBenString.Create; SetLength(StrValue.FValue,Fint); Move(p^,Pointer(StrValue.FValue)^,FInt*Sizeof(Char)); if List = nil then begin StrValue.FParent := Self; FList.Add(StrValue); end else begin StrValue.FParent := List; List.FList.Add(StrValue) end; Inc(p,Fint); end; end; end; end; function TDxBenList.ToString: string; var i: Integer; V: TDxBenValue; begin for i := 0 to FList.Count - 1 do begin V := FList[i]; Result := Result V.ToString; end; end; { TDxBenDictionary } procedure TDxBenDictionary.Clear; var Pair: TPair<string,TDxBenValue>; begin for Pair in FDict do begin Pair.Value.Free; end; FDict.Clear; end; constructor TDxBenDictionary.Create; begin FDict := TDictionary<string,TDxBenValue>.Create; end; destructor TDxBenDictionary.Destroy; begin Clear; FDict.Free; inherited; end; function TDxBenDictionary.GetAsInteger: Integer; begin raise Exception.Create('字典不支持'); end; function TDxBenDictionary.GetAsString: string; begin raise Exception.Create('字典不支持'); end; function TDxBenDictionary.GetCount: Integer; begin Result := FDict.Count; end; function TDxBenDictionary.GetObject: TDxBenValue; begin Result := Self; end; function TDxBenDictionary.GetType: TDxBenValueTypes; begin Result := DBV_Dictionary; end; function TDxBenDictionary.GetValues(Key: string): TDxBenValue; begin if FDict.ContainsKey(Key) then Result := FDict[Key] else Result := nil; end; procedure TDxBenDictionary.Parser(str: string); var len: Integer; p: PChar; begin len := Length(str); Clear; if (UpperCase(str[1]) = 'D') and (UpperCase(str[len]) = 'E') then begin Str := Copy(str,2,len - 2); p := @str[1]; ParserToDictionary(p,Self); end else raise Exception.Create('无效的B编码字典格式'); end; procedure TDxBenDictionary.ParserToDictionary(var p: PChar; Dict: TDxBenDictionary); type TParserState = (PS_None,PS_Key,PS_Value); var t: Char; st: string; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; Parstate: TParserState; key: string; begin //开始解析 Parstate := PS_None; while p^ <> '' do begin t := P^; case t of 'i': begin //整数 if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); st := ''; while p^ <> 'e' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; IntValue.FParent := Dict; Dict.FDict[Key] := IntValue; Inc(p); Parstate := PS_None; end; 'l': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); ListValue := TDxBenList.Create; ListValue.FParent := Dict; Dict.FDict[Key] := ListValue; ParserToList(p,ListValue); Parstate := PS_None; end; 'd': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); Inc(p); DicValue := TDxBenDictionary.Create; DicValue.FParent := Dict; Dict.FDict[Key] := DicValue; ParserToDictionary(p,DicValue); Parstate := PS_None; end; 'e': begin if Parstate = PS_Value then Parstate := PS_None else if Parstate = PS_None then Break; end; else begin st := ''; while p^ <> ':' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); //读取字符串 Inc(p); if StrLen(p) < FInt then raise Exception.Create('字符串解析长度不够'); SetLength(st,Fint); Move(p^,Pointer(St)^,FInt*Sizeof(Char)); Inc(p,Fint); if Parstate = PS_None then begin key := st; if Dict.FDict.ContainsKey(st) then raise Exception.Create('字典存在重复信息'); Dict.FDict.Add(st,nil); Parstate := PS_Value; end else if Parstate = PS_Value then begin StrValue := TDxBenString.Create; StrValue.FParent := Dict; StrValue.FValue := st; Dict.FDict[Key] := StrValue; Parstate := PS_None; end; end; end; end; end; procedure TDxBenDictionary.ParserToList(var P: Pchar; List: TDxBenList); var t: Char; st: string; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; begin //开始解析 while p^ <> '' do begin t := P^; case t of 'i': begin //是一个整数 Inc(p); st := ''; while p^ <> 'e' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; IntValue.FParent := List; List.FList.Add(IntValue); Inc(p); end; 'l': begin //列表 Inc(p); ListValue := TDxBenList.Create; ListValue.FParent := List; List.FList.Add(ListValue); ParserToList(p,ListValue); end; 'd': begin //字典 Inc(p); DicValue := TDxBenDictionary.Create; DicValue.FParent := List; List.FList.Add(DicValue); ParserToDictionary(p,DicValue); end; 'e': Break;//结束了 else begin //字符串 st := ''; while p^ <> ':' do begin if not CharInSet(p^, ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st p^; Inc(p); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); //读取字符串 Inc(p); if StrLen(p) < FInt then raise Exception.Create('字符串解析长度不够'); StrValue := TDxBenString.Create; SetLength(StrValue.FValue,Fint); Move(p^,Pointer(StrValue.FValue)^,FInt*Sizeof(Char)); StrValue.FParent := List; List.FList.Add(StrValue); Inc(p,Fint); end; end; end; end; function TDxBenDictionary.ToString: string; begin end; { TDxTorrentFile } procedure TDxTorrentFile.Clear; begin FDict.Clear; end; constructor TDxTorrentFile.Create; begin inherited; FDict := TDxBenDictionary.Create; end; destructor TDxTorrentFile.Destroy; begin FDict.Free; inherited; end; function TDxTorrentFile.Getannounce: string; var F: TDxBenValue; begin F := FDict.Values['announce']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxTorrentFile.Getannounce_list: TDxBenList; begin Result := TDxBenList(FDict.Values['announce-list']); end; function TDxTorrentFile.GetBtInfo: TDxBtInfo; begin Result := TDxBtInfo(FDict.Values['info']); end; function TDxTorrentFile.GetComment: string; begin if FDict.FDict.ContainsKey('comment') then begin if CompareText(Encoding,'utf-8') = 0 then Result := UTF8Decode(FDict.Values['comment'].AsString) else result := FDict.Values['comment'].AsString end else result := ''; end; function SpanOfNowAndThen(const ANow, AThen: TDateTime): TDateTime; begin if ANow < AThen then Result := AThen - ANow else Result := ANow - AThen; end; function SecondSpan(const ANow, AThen: TDateTime): Double; begin Result := SecsPerDay * SpanOfNowAndThen(ANow, AThen); end; function TDxTorrentFile.GetCreateDate: TDateTime; var F: TDxBenValue; V: Double; begin F := FDict.Values['creation date']; if F <> nil then begin //是从1970年1月1日00:00:00到现在的秒数 Result := F.AsInteger; //V := StrToDate('1970-01-01');//25569 V := SecondSpan(Now,25569); V := (V - Result) / SecsPerDay; Result := Now - V end else Result := 0; end; function TDxTorrentFile.GetCreator: string; var F: TDxBenValue; begin F := FDict.Values['created by']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxTorrentFile.GetEncoding: string; begin if FDict.Values['encoding'] <> nil then Result := FDict.Values['encoding'].AsString else result := ''; end; procedure TDxTorrentFile.LoadFromFile(FileName: string); var F: TFileStream; begin F := TFileStream.Create(FileName,fmOpenRead); LoadFromStream(F); F.Free; end; procedure TDxTorrentFile.LoadFromStream(Stream: TStream); var c: Byte; begin Clear; Stream.ReadBuffer(c,1); if Char(c) = 'd' then ParserStream(Stream,FDict); end; procedure TDxTorrentFile.ParserStreamToList(Stream: TStream; List: TDxBenList); var t: Byte; st: Ansistring; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; begin while Stream.Position <> Stream.Size do begin Stream.ReadBuffer(t,SizeOf(t)); case Char(t) of 'i': begin //是一个整数 st := ''; Stream.ReadBuffer(t,SizeOf(t)); while Char(t) <> 'e' do begin if not CharInSet(Char(t), ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st Char(t); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; IntValue.FParent := List; List.FList.Add(IntValue); end; 'l': begin //列表 ListValue := TDxBenList.Create; ListValue.FParent := List; List.FList.Add(ListValue); ParserStreamToList(Stream,ListValue); end; 'd': begin DicValue := TDxBenDictionary.Create; DicValue.FParent := List; List.FList.Add(DicValue); ParserStream(Stream,DicValue); end; 'e': Break; else begin st := ''; while Char(t) <> ':' do begin if not CharInSet(Char(t), ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st Char(t); Stream.ReadBuffer(t,SizeOf(t)); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); //读取字符串 if Stream.Size - Stream.Position < FInt then raise Exception.Create('字符串解析长度不够'); SetLength(st,Fint); Stream.ReadBuffer(Pointer(st)^,Fint); StrValue := TDxBenString.Create; if CompareText(Encoding,'utf-8') = 0 then StrValue.FValue := UTF8Decode(st) else StrValue.FValue := st; StrValue.FParent := List; List.FList.Add(StrValue); end; end; end; end; procedure TDxTorrentFile.ParserStream(Stream: TStream;Dict: TDxBenDictionary); type TParserState = (PS_None,PS_Key,PS_Value); var t: Byte; st: Ansistring; FInt: Integer; IntValue: TDxBenInt; ListValue: TDxBenList; StrValue: TDxBenString; DicValue: TDxBenDictionary; Parstate: TParserState; key: string; begin Parstate := PS_None; while Stream.Position < Stream.Size do begin Stream.ReadBuffer(t,SizeOf(t)); case Char(t) of 'i': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); st := ''; Stream.ReadBuffer(t,SizeOf(t)); while Char(t) <> 'e' do begin if not CharInSet(Char(t), ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st Char(t); Stream.ReadBuffer(t,SizeOf(t)); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型i' st 'e'); IntValue := TDxBenInt.Create; IntValue.FValue := FInt; IntValue.FParent := Dict; Dict.FDict[Key] := IntValue; Parstate := PS_None; end; 'l': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); ListValue := TDxBenList.Create; ListValue.FParent := Dict; Dict.FDict[Key] := ListValue; ParserStreamToList(Stream,ListValue); Parstate := PS_None; end; 'd': begin if Parstate <> PS_Value then raise Exception.Create('B编码字典的Key必须是字符串!'); DicValue := TDxBenDictionary.Create; DicValue.FParent := Dict; Dict.FDict[Key] := DicValue; ParserStream(stream,DicValue); Parstate := PS_None; end; 'e': begin if Parstate = PS_Value then Parstate := PS_None else if Parstate = PS_None then Break; end; else begin st := ''; while Char(t) <> ':' do begin if not CharInSet(Char(t), ['-','0'..'9']) then raise Exception.Create('无效的数据类型'); st := st Char(t); Stream.ReadBuffer(t,SizeOf(t)); end; if not TryStrToInt(st,FInt) then raise Exception.Create('无效的数据类型' st); if Stream.Size - Stream.Position < FInt then raise Exception.Create('字符串解析长度不够'); SetLength(st,Fint); Stream.ReadBuffer(Pointer(st)^,Fint); if Parstate = PS_None then begin key := st; if Dict.FDict.ContainsKey(st) then raise Exception.Create('字典存在重复信息'); Dict.FDict.Add(st,nil); Parstate := PS_Value; end else if Parstate = PS_Value then begin StrValue := TDxBenString.Create; StrValue.FParent := Dict; if CompareText(Encoding,'utf-8') = 0 then StrValue.FValue := UTF8Decode(st) else StrValue.FValue := st; Dict.FDict[Key] := StrValue; Parstate := PS_None; end; end; end; end; end; { TDxBtInfo } function TDxBtInfo.GetFiles: TDxBenList; begin Result := TDxBenList(Values['files']) end; function TDxBtInfo.GetName: string; var F: TDxBenValue; begin F := Values['name']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.GetNameUtf8: string; var F: TDxBenValue; begin F := Values['name.utf-8']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.Getpublisher: string; var F: TDxBenValue; begin F := Values['publisher']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.Getpublisherurl: string; var F: TDxBenValue; begin F := Values['publisher-url']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.GetpublisherurlUtf8: string; var F: TDxBenValue; begin F := Values['publisher-url.utf8']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.GetpublisherUtf8: string; var F: TDxBenValue; begin F := Values['publisher.utf-8']; if F <> nil then Result := F.AsString else Result := ''; end; function TDxBtInfo.GetSingleFile: Boolean; begin Result := Files = nil; end; end.