Home

Awesome

build docs santizers GitHub release (latest SemVer) C++ standard Codacy Badge codecov License: MIT

Features | Status | Documentation | Performance | Examples | Building | Integration | License

A header-only C++20 bencode serialization/deserialization library.

Features

Status

This library is under active development. The API may change at any release prior to 1.0.0. Versioning follows the Semantic Versioning Specification.

Documentation

Documentation is available on the bencode GitHub pages

Performance

Decoding performance was benchmarked for both value and view types. Value types own the data they refer to and thus need to copy data from the buffer with bencoded data. View types try to minimize copies from the buffer with bencoded data and instead point to data directly inside the buffer.

Decoding speed was compared for these libraries in alphabetical order:

Parsing to value types

benchmark-decoding-value

Parsing to view types

benchmark-decoding-view

All benchmarks were build with GCC 10.2.1 with -O3 and run on an intel i7-7700hq.

Notes:

Examples

// All examples use namespace bc for brevity
namespace bc = bencode;

Decode bencoded data to bvalue.

//#include <bencode/bencode.hpp> 

namespace bc = bencode;

bc::bvalue b = bc::decode_value("l3:fooi2ee");

// check if the first list element is a string
if (holds_list(b) && holds_string(b[0])) {
    std::cout << "success";
}

// type tag based type check, return false
bc::holds_alternative<bc::type::dict>(b); 

// access the first element of the list "foo" and move it 
// out of the bvalue into v1
std::string v1 = bc::get_string(std::move(b[0]));

// access the second element
std::size_t v2 = bc::get_integer(b[1]);

Serialize a bvalue to an output stream.

bc::bvalue b{
  {"foo", 1},
  {"bar", 2},
  {"baz", bc::bvalue(bc::btype::list, {1, 2, 3})},
};

bc::encode_to(std::cout, b);

Retrieve data from a bvalue.

auto b = bc::bvalue(bc::type::list, {1, 2, 3, 4, 5, 6, 7, 8, 9});

// return a list of integers as a byte vector, throws on error
auto bytes = get_as<std::vector<std::byte>>(b);

// non throwing version with a std::expected type
auto res = try_get_as<std::vector<std::byte>>(b);

if (res.has_value()) {
    std::cout << res.value(); 
} else {
    std::cout << "error" << to_string(res.error());
}

Decode bencoded data to bview.

//#include <bencode/bview.hpp> 

namespace bc = bencode;

// decode the data to a descriptor_table
bc::descriptor_table t = bc::decode_view("l3:fooi2ee");

// get the bview to the root element (ie the list) 
bc::bview b = t.get_root();

// access data and convert to std::size_t and std::string_view
std::string_view v1 = bc::get_string(b[0]);
std::size_t v2 = bc::get_integer(b[1]);

Serialize to bencode using encoder.

#include <bencode/encode.hpp>
#include <bencode/traits/vector.hpp>    

bc::encoder es(std::cout);

es << bc::dict_begin
       << "foo" << 1UL
       << "bar" << bc::list_begin 
                    << bc::bvalue(1)
                    << "two" 
                    << 3
                << bc::list_end
       << "baz" << std::vector{1, 2, 3}
   << bc::dict_end;

Use bpointer to access values in a nested datastructure.

bc::bvalue b {
    {"foo", 1},
    {"bar", 2},
    {"baz", bc::bvalue(bc::btype::list, {1, 2, 3})},
};

b.at("baz/2"_bpointer);

See the documentation for more examples.

Building

This project requires C++20. Supported compilers are:

This library uses following projects:

When building tests:

When building benchmarks:

When building documentation:

All dependencies except for boost, Qt5 and documentation dependencies can be fetched from github using cmake FetchContent during configuration if no local installation is found.

The tests can be built as every other project which makes use of the CMake build system.

mkdir build; cd build;
cmake \
  -DCMAKE_BUILD_TYPE=Debug \
  -DBENCODE_BUILD_TESTS=ON \
  -DBENCODE_BUILD_BENCHMARKS=OFF \
  -DBENCODE_BUILD_DOCS=OFF \
   --build . --target .. 
make bencode-tests

The library can be installed as a CMake package.

cmake -DBENCODE_BUILD_TESTS=OFF \
      -DBENCODE_BUILD_BENCHMARKS=OFF \
      -DBENCODE_BUILD_DOCS=OFF --build . --target ..
sudo make install

Integration

You can use the bencode::bencode interface target in CMake. The library can be located with find_package.

# CMakeLists.txt
find_package(bencode REQUIRED)
...
add_library(foo ...)
...
target_link_libraries(foo INTERFACE bencode::bencode)

The source tree can be included in your project and added to your build with add_subdirectory.

# CMakeLists.txt
add_subdirectory(bencode)
...
add_library(foo ...)
...
target_link_libraries(foo INTERFACE bencode::bencode)

You can also use FetchContent to download the source code from github.

# CMakeLists.txt
include(FetchContent)

FetchContent_Declare(bencode
  GIT_REPOSITORY https://github.com/fbdtemme/bencode.git
  GIT_TAG "master")

FetchContent_MakeAvailable(bencode)
...
add_library(foo ...)
...
target_link_libraries(foo INTERFACE bencode::bencode)

License

Distributed under the MIT license. See LICENSE for more information.