Bencoding encoder

xiaoxiao2021-03-06  36

The BT client starts a download first to process is the Torrent file. The Torrent file uses Bencoding encoding. So the Bencoding encoded parser is the first step. Bencoding is Done as Follows: strings are length-prefixed base ten Followed by A colon and the string. for example / '4: spam /' corresponds to / 'spam /'. Integers are represented by an / 'i /' backed by the number in base 10 Followed by AN / 'E /'. for Example / 'I3E /' Corresponds to 3 and / 'i-3e /' Corresponds To -3. Integers Have No Size Limitation. All Encodings with a Leading Zero, Such AS / 'I03E / ', Are Invalid, Other Than /' i0e / ' / 'L4: Spam4: Eggse /' Corresponds To [/ 'spam /', / 'eggs /']. Dictionaries Are Encoded A / 'D /' Followed by A List of Alternating Keys and Their Corresponding Values ​​Followed by AN / 'E /'. for Example, / 'D3: COW3: MOO4: SPAM4: Eggse /' Corresponds to {/ 'COW /': / 'MOO /', / 'SPAM /': / 'Eggs /'} and / ' 'D4: Spaml1: a1: Bee /' Corresponds to {/ 'SP AM / ': [/' A / ', /' B / ']}. Keys Must Be strings and APPEAR in Sorted Order (sorted as raw strings, not alphaplerics). The following is the VC source code for the Bencoding decoder implemented:

// Bencode.h: Interface for the cbencode class.

//

//

#if! defined (AFX_BENCODE_H___4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_)

#define AFX_BENCODE_H__4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_

#iF _MSC_VER> 1000

#pragma overce

#ENDIF / / 100 m _ _

#pragma Warning (Disable: 4786)

#pragma Warning (Disable: 4355)

#include

#include

#include #include

Using namespace std;

ENUM BENCODEPARSERRRORCODE

{

ENM_BENCODEERR_NOERR = 0, // No error

ENM_BENCODEERR_ERRSTRING, / / ​​Error string

ENM_BENCODEERR_ERRINT, / / ​​Error integer data

ENM_BENCODEERR_ERRLIST, / / ​​Error list

ENM_BENCODEERR_ERRDICT, / / ​​Error Dictionary

ENM_BENCODEERR_END, // The text ends

ENM_BENCODEERR_UNKNOWN / / unknown error

}

ENUM BENCODEOBJECTTYPE

{

ENUM_BENCODETYPE_ObjectBase = 0,

ENUM_BENCODETYPE_STRING,

Enum_bencodetype_int,

ENUM_BENCODETYPE_LIST,

ENUM_BENCODETYPE_DICT,

}

Class CbencodeObjectBase

{

PUBLIC:

CbencodeObjectBase (BencodeObjectType Type = Enum_Bencodtype_ObjectBase) {m_type = type; clear ();

Virtual ~ cbencodeObjectBase () {};

Void clear () {szpos = null; m_ERROR = enm_bencodeerr_noerr;}

PUBLIC:

BencodeObjectType M_Type; // Object Type

CHAR * SZPOS; // Location in the string

INT Ilen; // Data length of the object

BencodeparsererrorCode M_ERROR; / / Error value

}

Class Cbencodeint: Public CbencodeObjectBase

{

PUBLIC:

Cbencodeint (): cbencodeObjectBase (enum_bencodetype_int) {}

Virtual ~ cbencodeint () {}

PUBLIC:

INT M_IVALUE; / / Total object value

}

Class Cbencodestring: Public CbencodeObjectBase

{

PUBLIC:

Cbencodestring (): cbencodeObjectBase (enum_bencodetype_string) {m_szdata = null;}

Virtual ~ cbencodestring () {}

PUBLIC:

Bool getString (String & Strvalue)

{

IF (m_error == enm_bencodeerr_noerr && m_szdata)

{

Strvalue.Assign (m_szdata, m_ilen);

Return True;

}

Return False;

}

Char * m_szdata;

Int m_ilen;

}

Class Cbencodelist: Public CbencodeObjectBase

{

PUBLIC:

Cbencodelist (): cbencodeObjectBase (enum_bencodettype_list) {}

Virtual ~ cbencodelist () {clear ();

void clear ()

{

List :: item.

For (it = m_listobj.begin (); it! = m_listobj.end (); IT) delete (* it);

m_listobj.clear ();

}

PUBLIC:

List m_listobj;

}

Class CbencodeDict: Public CbencodeObjectBase

{

PUBLIC:

Cbencodedict (): cbencodeObjectBase (enum_bencodetype_dict) {}

Virtual ~ cbencodededict () {clear ();

CbencodeObjectBase * getValue (const char * szname)

{

Map :: itemarator it = m_mapobj.find (szname);

IF (it! = m_mapobj.end ())

Return it-> second;

Return NULL;

}

void clear ()

{

List :: item.

For (it = m_listobj.begin (); it! = m_listobj.end (); IT)

Delete (* it);

m_listobj.clear ();

m_mapobj.clear ();

}

PUBLIC:

Map m_mapobj; //

List m_listobj; // The real object is saved in the list, and List is a value object. Map is just a mapping table, reference the pointer.

}

Class cbencode

{

PUBLIC:

Bool Readint (Char * Szcurpos, Int & IendPos, List & listobj);

Bool ReadString (Char * Szcurpos, Int & Iendpos, List & Listobj);

Bool Readlist (Char * Szcurpos, Int & IendPos, List & listobj);

Bool ReadDict (Char * Szcurpos, Int & IendPos, List & Listobj);

BOOL PARSE (Const Char * Szdata);

CBENCODE ();

Virtual ~ cbencode ();

void clear ()

{

List :: item.

For (it = m_listobj.begin (); it! = m_listobj.end (); IT)

Delete (* it);

m_listobj.clear ();

}

PUBLIC:

List m_listobj;

CbencodeObjectBase * m_plastobj; // The last object of the resolution

Char * m_sztxt;

}

#ndif //! defined (AFX_BENCODE_H__4D0BB462_2AE0_45B3_8BE8_19D51B2DBB2E__INCLUDED_)

// Bencode.cpp: Implementation of the cbencode class.//

//

#include "stdafx.h"

#include "bencode.h"

//

// construction / destruction

//

Cbencode :: cbencode ()

{

m_plastobj = NULL;

m_sztxt = NULL;

}

Cbencode :: ~ cbencode ()

{

Clear ();

}

Bool Cbencode :: Parse (Const Char * Szdata)

{

IF (szdata == null || * szdata == NULL)

Return False;

Clear ();

m_sztxt = (char *) szdata;

Char * szcurpos = (char *) SZDATA;

INT IENDPOS;

While (* szcurpos)

{

IF (* szcurpos == 'i')

{

IF (! Readint (szcurpos, iendpos, m_listobj))

Break; // encountered any error to terminate the entire resolution

Szcurpos = IENDPOS;

}

ELSE IF (* szcurpos == 'L')

{

IF (! Readlist (Szcurpos, IENDPOS, M_LISTOBJ))

Break;

Szcurpos = IENDPOS;

}

ELSE IF (* szcurpos == 'd')

{

IF (! readdict (szcurpos, iendpos, m_listobj))

Break;

Szcurpos = IENDPOS;

}

Else

{

IF (! ReadString (Szcurpos, IENDPOS, M_LISTOBJ))

Break;

Szcurpos = IENDPOS;

}

}

IF (* szcurpos == 0 && m_plastobj-> m_error == enm_bencodeerr_noerr)

Return True;

Return False;

}

// Read a string from the current location

Bool Cbencode :: ReadString (Char * Szcurpos, Int & Iendpos, List & Listobj)

{

Char * sztmp = szcurpos;

Cbencodestring * pnewstring = new cbencodestring;

Pnewstring-> szpos = szcurpos;

Char Szlen [20];

INT i = 0;

While (* sztmp> = '0' && * sztmp <= '9')

Szlen [i ] = * (SZTMP );

Szlen [I] = 0;

IF (* sztmp == ':')

{

Ilen = ATOI (Szlen);

IF (Ilen> 0)

{

Pnewstring-> m_szdata = sztmp;

Pnewstring-> m_ilen = Ilen;

SZTMP = Ilen;

}

Else

Pnewstring-> m_ERROR = ENM_BENCODEERR_ERRSTRING;

Else

Pnewstring-> m_ERROR = ENM_BENCODEERR_ERRSTRING;

Listobj.push_back (pnewstring);

IENDPOS = SZTMP-SZCURPOS;

m_plastobj = pnewstring;

M_Plastobj-> Ilen = IendPos;

Return pnewstring-> m_error == enm_bencodeerr_noerr? True: false;

}

// Read a integer data

Bool Cbencode :: Readint (Char * Szcurpos, Int & Iendpos, List & Listobj)

{

Char * sztmp = szcurpos;

Cbencodeint * pnewint = new cbencode;

Pnewint-> szpos = szcurpos;

IF (* sztmp == 'i')

{

SZTMP ;

Char Szlen [20];

INT i = 0;

While (* sztmp> = '0' && * sztmp <= '9')

Szlen [i ] = * (SZTMP );

Szlen [I] = 0;

IF (* sztmp == 'e')

{

PNEWINT-> M_IVALUE = ATOI (SZLEN);

SZTMP;

}

Else

PNEWINT-> M_ERROR = ENM_BENCODEERR_ERRINT;

}

Else

PNEWINT-> M_ERROR = ENM_BENCODEERR_ERRINT;

Listobj.push_back (pnewint);

IENDPOS = SZTMP-SZCURPOS;

m_plastobj = pnewint;

M_Plastobj-> Ilen = IendPos;

Return Pnewint-> m_ERROR == ENM_BENCODEERR_NOERR? TRUE: FALSE;

} // Read a list

Bool Cbencode :: Readlist (Char * Szcurpos, Int & Iendpos, List & Listobj)

{

Char * sztmp = szcurpos;

Cbencodelist * pnewlist = new cbencodelist;

PNewlist-> szpos = szcurpos;

IF (* sztmp == 'L')

{

SZTMP ;

Int ilistendpos;

While (* sztmp! = 'e')

{

IF (* sztmp == 'i')

{

IF (! readint (sztmp, ilistendpos, pnewlist-> m_listobj))

Break; // encountered any error to terminate the entire resolution

Sztmp = ilistendpos;

}

ELSE IF (* sztmp == 'L')

{

IF (! Readlist (sztmp, ilistendpos, pnewlist-> m_listobj)) Break;

Sztmp = ilistendpos;

}

ELSE IF (* sztmp == 'd')

{

IF (! readdict (sztmp, ilistendpos, pnewlist-> m_listobj))

Break;

Sztmp = ilistendpos;

}

Else

{

IF (! readstring (sztmp, ilistendpos, pnewlist-> m_listobj))

Break;

Sztmp = ilistendpos;

}

}

IF (* sztmp! = 'e' || m_plastobj-> m_error! = ENM_BENCODEERR_NOERR)

Pnewlist-> m_error = enm_bencodeerr_errlist;

Else

SZTMP ;

}

Else

Pnewlist-> m_error = enm_bencodeerr_errlist;

Listobj.push_back (pnewlist);

IENDPOS = SZTMP-SZCURPOS;

m_plastobj = pnewlist;

M_Plastobj-> Ilen = IendPos;

Return PNewlist-> m_error == ENM_BENCODEERR_NOERR? TRUE: FALSE;

}

// Read a dictionary

Bool Cbencode :: ReadDict (Char * Szcurpos, Int & Iendpos, List & Listobj)

{

Char * sztmp = szcurpos;

Cbencodedict * pnewdict = new cbencoded

PNewdict-> szpos = szcurpos;

IF (* sztmp == 'd')

{

SZTMP ;

Int ilistendpos;

String strname;

While (* sztmp! = 'e')

{

IF (! readstring (sztmp, ilistendpos, pnewdict-> m_listobj))

Break;

IF (m_plastobj-> m_type! = enum_bencodorepe_string)

Break;

Strname.assign ((cbencodestring *) m_plastobj) -> m_szdata, ((cbencodestring *) m_plastobj) -> m_ilen);

Sztmp = ilistendpos;

IF (* sztmp == 'i')

{

IF (! readint (sztmp, ilistendpos, pnewdict-> m_listobj))

Break; // encountered any error to terminate the entire resolution

Sztmp = ilistendpos;

}

ELSE IF (* sztmp == 'L')

{

IF (! readlist (sztmp, ilistendpos, pnewdict-> m_listobj))

Break;

Sztmp = ilistendpos;

}

ELSE IF (* sztmp == 'd')

{

IF (! ReadDict (SzTMP, ILISTENDPOS, PNEWDICT-> M_LISTOBJ) Break;

Sztmp = ilistendpos;

}

Else

{

IF (! readstring (sztmp, ilistendpos, pnewdict-> m_listobj))

Break;

Sztmp = ilistendpos;

}

PNewDict-> m_mapobj.insert (Pair );

}

IF (* sztmp! = 'e' || m_plastobj-> m_error! = ENM_BENCODEERR_NOERR)

PNEWDICT-> M_ERROR = ENM_BENCODEERR_ERRDICT;

Else

SZTMP ;

}

Else

PNEWDICT-> M_ERROR = ENM_BENCODEERR_ERRDICT;

Listobj.push_back (pnewdict);

IENDPOS = SZTMP-SZCURPOS;

m_plastobj = pnewdict;

M_Plastobj-> Ilen = IendPos;

Return PNewdict-> m_error == ENM_BENCODEERR_NOERR? TRUE: FALSE;

}

转载请注明原文地址:https://www.9cbs.com/read-71229.html

New Post(0)