GithubHelp home page GithubHelp logo

fbdtemme / bencode Goto Github PK

View Code? Open in Web Editor NEW
42.0 5.0 5.0 20.19 MB

A C++20 header-only bencode library.

License: MIT License

CMake 1.98% C++ 85.86% Jupyter Notebook 11.56% Python 0.35% Shell 0.25%
bencode bittorrent cpp20 serialization bencode-parser deserialization bencoder

bencode's Introduction

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

  • Feature-rich. The main goal of this library is to provide a complete bencode library that provides optimal solutions for all common use cases. bvalue is an owning representation of bencoded data and is usefull for creating and modifying bencoded documents. bview is a fast and memory efficient, read-only, non-owning representation into a stable buffer of bencoded data. bpointer can be used to access both bvalue and bview types.
  • Extensibility. This library provides built-in serialization and deserialization from/to most standard containers. Support for user-defined types can be added by implementing the necessary extension points. Users can parse directly to their data type of preference by implementing a class satisfying the EventConsumer concept.
  • Conformance. This library is 100% conforming to the bencode specification. All parsers validate the input and provide exact error messages.
  • Security. Parsing arbitrary user data can be dangerous and you do not want your bittorrent tracker to crash when a user sends malformed data. All parsers are recursion-free to protect against stack-based buffer overflow attacks. Integer parsing throws when overflows are encountered.
  • Speed. While not the primary goal of this project this library provides optimized integer parsing with SWAR techniques. Benchmarks show this library performs well in comparison with other libraries
  • Well-tested. This project achieves 95% testing coverage. We also run Sanitizers in a CI pipeline to check for leaks and undefined-behavior.

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:

  • arvidn/libtorrent does not decode integers until they are actually accessed. This gives a performance benefit when decoding but results in slower access times when retrieving integral values.
  • kriben/bencode support only 32-bit integers and fails on the camelyon17, integers and pneumomia benchmarks
  • iRajul/bencode fails all benchmarks and was excluded from the results.

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:

  • GCC >= 10
  • MinGW >= 10
  • MSVC >= 19.30

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.

bencode's People

Contributors

codacy-badger avatar fbdtemme avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

bencode's Issues

Build errors with deps and instructions

  1. Your makefile is not fetching the 3 libs dependancies : fmt, gsl-lite, expected-lite
  • I had to compile and install them separatly for the build to find them.
  • CMake error type :
CMake Error at CMakeLists.txt (find_package):                                                                                                                     
  Could not find a package configuration file provided by "gsl-lite" with any                                                                                                                
  of the following names:                                                                                                                                                                    
                                                                                                                                                                                             
    gsl-liteConfig.cmake                                                                                                                                                                     
    gsl-lite-config.cmake                                                                                                                                                                    
                                                                                                                                                                                             
  Add the installation prefix of "gsl-lite" to CMAKE_PREFIX_PATH or set                                                                                                                      
  "gsl-lite_DIR" to a directory containing one of the above files.  If                                                                                                                       
  "gsl-lite" provides a separate development package or SDK, be sure it has                                                                                                                  
  been installed.
  1. Cmake don't like your instruction for a release build and it miss the build type.
  • Updated instruction :
git clone --depth=1 https://github.com/fbdtemme/bencode
cd bencode; mkdir build; cd build
cmake -DCMAKE_BUILD_TYPE=Release
      -DBENCODE_BUILD_TESTS=OFF \
      -DBENCODE_BUILD_BENCHMARKS=OFF \
      -DBENCODE_BUILD_DOCS=OFF \
      ..
sudo make install

How to generate the project files for this and build?

After I clone the repository and run cmake CMakeLists.txt, I get:

-- Building for: Visual Studio 17 2022
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19045.
-- The CXX compiler identification is MSVC 19.36.32537.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Tools/MSVC/14.36.32532/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:30 (find_package):
  Could not find a package configuration file provided by "fmt" with any of
  the following names:

    fmtConfig.cmake
    fmt-config.cmake

  Add the installation prefix of "fmt" to CMAKE_PREFIX_PATH or set "fmt_DIR"
  to a directory containing one of the above files.  If "fmt" provides a
  separate development package or SDK, be sure it has been installed.


-- Configuring incomplete, errors occurred!

The fmt library doesn't have fmtConfig.cmake or fmt-config.cmake files anywhere in the repository.

1.0.1 not listed as release

Some probably nitpick and minor observations:

  • There is no entry for the 1.0.1 release on the releases page.
  • The 1.0.1 tag does not have the "v" prefix as previous releases/tags did.
  • The changelog mentions it with "v" prefix.
  • The changelog mentions a v1.0.0, which was never tagged or listed among the releases (this is probably fine).

compiler error

had to add T tmp; at

if (__builtin_mul_overflow(val, sign, &tmp)) {

[ 37%] Building CXX object _deps/yaml-cpp-build/CMakeFiles/yaml-cpp.dir/src/parser.cpp.o
In file included from /home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/detail/parser/from_chars.hpp:12,
                 from /home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/detail/bpointer.hpp:12,
                 from /home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/detail/bvalue/pointer.hpp:4,
                 from /home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/bvalue.hpp:12,
                 from /home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/bencode.hpp:3,
                 from /home/skydrome/torrenttools/build/_deps/dottorrent-src/include/dottorrent/announce_url.hpp:13,
                 from /home/skydrome/torrenttools/build/_deps/dottorrent-src/include/dottorrent/announce_url_list.hpp:4,
                 from /home/skydrome/torrenttools/build/_deps/dottorrent-src/src/announce_url_list.cpp:2:
/home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/detail/parser/implementation/from_chars_sse41.hpp: In function 'constexpr bencode::detail::from_chars_result bencode::detail::from_chars(const char*, const char*, T&, bencode::detail::implementation_tag<2>)':
/home/skydrome/torrenttools/build/_deps/bencode-src/include/bencode/detail/parser/implementation/from_chars_sse41.hpp:274:44: error: 'tmp' was not declared in this scope; did you mean 'tm'?
274 |     if (__builtin_mul_overflow(val, sign, &tmp)) {
    |                                            ^~~
    |                                            tm

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.