| libtorrent

Author: | Arvid Norberg, arvid@libtorrent.org
Version: | 1.2.16

home

# Bencoding

Table of contents

- Bencoding
  - entry
  - operator<<()
  - bencode()

Bencoding is a common representation in bittorrent used for dictionary, list, int and string hierarchies. It's used to encode .torrent files and some messages in the network protocol. libtorrent also uses it to store settings, resume data and other session state.

Strings in bencoded structures do not necessarily represent text. Strings are raw byte buffers of a certain length. If a string is meant to be interpreted as text, it is required to be UTF-8 encoded. See BEP 3.

The function for decoding bencoded data bdecode(), returning a bdecode_node. This function builds a tree that points back into the original buffer. The returned bdecode_node will not be valid once the buffer it was parsed out of is discarded.

It's possible to construct an entry from a bdecode_node, if a structure needs to be altered and re-encoded.

[report issue]

## entry

Declared in "libtorrent/entry.hpp"

The `entry` class represents one node in a bencoded hierarchy. It works as a variant type, it can be either a list, a dictionary (`std::map`), an integer or a string.

    class entry
    {
       data_type type () const;
       entry (list_type); // NOLINT;
       entry& operator= (preformatted_type) &;
       entry& operator= (list_type) &;
       entry (dictionary_type); // NOLINT;
       entry& operator= (integer_type) &;
       const string_type& string () const;
       dictionary_type& dict ();
       const preformatted_type& preformatted () const;
       string_type& string ();
       const dictionary_type& dict () const;
       const integer_type& integer () const;
       integer_type& integer ();
       preformatted_type& preformatted ();
       list_type& list ();
       const list_type& list () const;
       void swap (entry& e);
       entry& operator[] (string_view key);
       const entry& operator[] (string_view key) const;
       entry const* find_key (string_view key) const;
       entry* find_key (string_view key);
       std::string to_string (bool single_line = false) const;

       enum data_type
       {
          int_t,
          string_t,
          list_t,
          dictionary_t,
          undefined_t,
          preformatted_t,
       };

       mutable std::uint8_t m_type_queried:1;
    };

[report issue]

### type()

    data_type type () const;

returns the concrete type of the entry

[report issue]

### entry() operator=()

    entry (list_type); // NOLINT;
    entry& operator= (preformatted_type) &;
    entry& operator= (list_type) &;
    entry (dictionary_type); // NOLINT;
    entry& operator= (integer_type) &;

constructors directly from a specific type. The content of the argument is copied into the newly constructed entry

[report issue]

### string() list() integer() preformatted() dict()

    const string_type& string () const;
    dictionary_type& dict ();
    const preformatted_type& preformatted () const;
    string_type& string ();
    const dictionary_type& dict () const;
    const integer_type& integer () const;
    integer_type& integer ();
    preformatted_type& preformatted ();
    list_type& list ();
    const list_type& list () const;

The `integer()`, `string()`, `list()` and `dict()` functions are accessors that return the respective type. If the `entry` object isn't of the type you request, the accessor will throw system_error. You can ask an `entry` for its type through the `type()` function.

If you want to create an `entry` you give it the type you want it to have in its constructor, and then use one of the non-const accessors to get a reference which you then can assign the value you want it to have.

The typical code to get info from a torrent file will then look like this:

    entry torrent_file;
    // ...

    // throws if this is not a dictionary
    entry::dictionary_type const& dict = torrent_file.dict();
    entry::dictionary_type::const_iterator i;
    i = dict.find("announce");
    if (i != dict.end())
    {
            std::string tracker_url = i->second.string();
            std::cout << tracker_url << "\n";
    }

The following code is equivalent, but a little bit shorter:

    entry torrent_file;
    // ...

    // throws if this is not a dictionary
    if (entry* i = torrent_file.find_key("announce"))
    {
            std::string tracker_url = i->string();
            std::cout << tracker_url << "\n";
    }

To make it easier to extract information from a torrent file, the class torrent_info exists.

[report issue]

### swap()

    void swap (entry& e);

swaps the content of this with `e`.

[report issue]

### operator[]()

    entry& operator[] (string_view key);
    const entry& operator[] (string_view key) const;

All of these functions requires the entry to be a dictionary, if it isn't they will throw `system_error`.

The non-const versions of the `operator[]` will return a reference to either the existing element at the given key or, if there is no element with the given key, a reference to a newly inserted element at that key.

The const version of `operator[]` will only return a reference to an existing element at the given key. If the key is not found, it will throw `system_error`.

[report issue]

### find_key()

    entry const* find_key (string_view key) const;
    entry* find_key (string_view key);

These functions requires the entry to be a dictionary, if it isn't they will throw `system_error`.

They will look for an element at the given key in the dictionary, if the element cannot be found, they will return nullptr. If an element with the given key is found, the return a pointer to it.

[report issue]

### to_string()

    std::string to_string (bool single_line = false) const;

returns a pretty-printed string representation of the bencoded structure, with JSON-style syntax

[report issue]

### enum data_type

Declared in "libtorrent/entry.hpp"

name | value | description
--- | --- | ---
int_t | 0 |
string_t | 1 |
list_t | 2 |
dictionary_t | 3 |
undefined_t | 4 |
preformatted_t | 5 |

[report issue]

m_type_queried
  in debug mode this is set to false by bdecode to indicate that the program has not yet queried the type of this entry, and should not assume that it has a certain type. This is asserted in the accessor functions. This does not apply if exceptions are used.

[report issue]

## operator<<()

Declared in "libtorrent/entry.hpp"

    inline std::ostream& operator<< (std::ostream& os, const entry& e);

prints the bencoded structure to the ostream as a JSON-style structure.

[report issue]

## bencode()

Declared in "libtorrent/bencode.hpp"

    template<class OutIt> int bencode (OutIt out, const entry& e);

This function will encode data to bencoded form.

The entry class is the internal representation of the bencoded data and it can be used to retrieve information, an entry can also be build by the program and given to `bencode()` to encode it into the `OutIt` iterator.

`OutIt` is an OutputIterator. It's a template and usually instantiated as ostream_iterator or back_insert_iterator. This function assumes the value_type of the iterator is a `char`. In order to encode entry `e` into a buffer, do:

    std::vector<char> buffer;
    bencode(std::back_inserter(buf), e);