Squashed 'third_party/protozero/' changes from d5d8debf1..f379578a3
f379578a3 Release 1.7.1 040947ba2 CMake: Add language C to project() c60e87879 Update include catch.hpp to 2.13.8 6599d4828 Update change log ebd2e4f40 Allow setting C++ version to compile with in CMake config bbb2a95d0 Github actions: Only install x64 version of vcpkgs in windows build 546edf929 Avoid narrowing conversion by being explicit 91adaecd6 Fix various issues reported by clang-tidy and disable some checks 68f30a1f7 Add Github actions CI build for Linux/macOS/Windows c13886b78 Update some links bd429c52f Include tools subdirectory *after* testing is enabled 3133dc52f Use std::memcpy instead of just memcpy 7ee29422a Merge pull request #106 from daniel-j-h/fix-byteswap-ub aba0800aa CMake config: clang-tidy target needs writer_tests which need protobuf 74516e8df Modernize CMake config a little bit b4486ca7a Disable some clang-tidy warnings 19f4b75f6 Fix appveyor build 58b1a19a4 Modernize Doxygen config file 046c07d0e Update included catch2 framework to current version v2.13.7 49acea746 fix some doxygen warnings by removing obsolete config entries 0c5426df3 fix cmake dep warning: 'Compatibility with CMake < 2.8.12 will be removed from a future version of CMake' dadf7bd51 Fixes float and double byteswap undefined behavior 85db94025 Merge pull request #105 from ffontaine/master d3a35791d Merge pull request #104 from joto/master 03daae49c CMakeLists.txt: respect BUILD_TESTING 67133e362 Add missing includes 9f85f3a5e Update README.md 010ffcf69 Release 1.7.0 6ad492994 Fixed docs adde4dedf Travis: Add non-Intel architectures 37c3d0e1d Add typedefs and functions to make buffer adaptor work as container 83563acdb Remove delegating constructor because clang-tidy doesn't like it b4afc06db Use #include "" for library-internal includes d1929788e Add missing includes fae5247f0 Update change log 2abb1b5cd Travis: Test with std::string_view, not std::experimental::string_view 697bd812d Use forwarding constructor in fixed_size_buffer_adaptor c8fd2e819 Move fixed_size_buffer_adaptor into buffer_fixed.hpp abb856ecc Remove semicolon where it doesn't belong 6243855bc Change the way the customization for special buffer classes work d6a8ed098 Remove useless post-increment 184046cb0 Remove need for push_back() on custom buffer types 0a974e067 Remove templated buffer adaptor wrappers ed6ba5097 Add buffer implementation based on std::vector<char> cec309c3c Use more descriptive names for buffer test types a7b99da6f Use TEMPLATE_TEST_CASE to test different buffer implementations a0abc493c Use explicit for constructor 72850abc9 Remove broken doxygen link 1e347c620 Add more convenient fixed_size_buffer_adaptor constructor fb575e0ea Make members private 50e953b71 Make older compilers happy c850ef150 Extend tests of static buffer use f6d8394c0 Rename fixed_size_buffer to fixed_size_buffer_adaptor 3b18162e3 Make the buffer backend used by the pbf writer configurable. 6fd19c58d "Modernize" travis config 981aba084 Use explicit cast to avoid undefined behaviour 550974d5d Travis: Do not test GCC 4.7 any more 866e024fc Revert "Workaround in catch code so it compiles with older compilers" 65dfad056 Disable a clang-tidy test triggered by Catch. 02bf73df5 Workaround in catch code so it compiles with older compilers f98792a15 Travis: Do not update homebrew for faster builds 2d87da7ec Switch tests to Catch2 5dc45ac3b Avoid signed/unsigned comparison 3a93f19ba Add missing includes b49c077ac Disable clang-tidy for files where we don't have a compile command 34396fc7d Travis: Fix gcc8 build c3060101c Handle clang-tidy warnings 64ef96ff0 Revert "Initialize test messages" a0828d538 Travis: Also build with GCC 8 171c5c446 Update travis xcode versions f5a223aa7 Use "auto*" instead of just "auto" for pointer types e4fa23616 Initialize test messages e3a59454a Simpler code and avoid shadowing of external function 830f049b4 Use STL algorithms insted of raw loops faa7e6e8a Disable config settings not used in newer Doxygen versions 3b2e11438 Remove unnecessary enum name 7487f8109 Release 1.6.8 6dcaf8fde Travis config: Use "official" way to pull homebrew package. c61eb29c3 Revert "Disable warnings from clang-tidy about a missing file." 28d05a0a8 Disable warnings from clang-tidy about a missing file. 329920a3c Pesky aliases of clang-tidy warnings strike again. 79fd87922 User plain assert() instead of our own so compare() can be noexcept. 473e6ec13 Update change log. 393e279b7 Make pbf_writer destructor noexcept. 48a38b3f2 Disable clang-tidy misc-non-private-member-variables-in-classes. e9c148c8a Use no-argument version of main(). 29ba04123 Disable clang tidy checks for C arrays. 2fcfb56e2 More places to use std::array instead of a C style array. 7321761a3 Disable a clang-tidy warning. 4d9d8fff4 Make data_view::compare() noexcept. 3325364cf User uppercase integer literal suffix. df0a23c5e Use std::array instead of C arrays in some places. 8247ed76b Make clang-tidy include order check happy. f1b504e16 Update travis config to user newer compilers and operating systems. ccf692d47 Disable some clang-tidy warnings. 095abd259 CMake config: Also look for newer clang-tidy versions. 2c1f6f9c8 Use uppercase integer literal suffixes. fadd024d4 Release 1.6.7 8c6acbff7 Fix signed-unsigned comparison. b36774ccb Release 1.6.6 5a92b744f Remove useless asserts, simplify condition. 06bafb56c Fix several possible UBs. b7b290b1a Release 1.6.5 51753d514 Merge pull request #95 from tomhughes/subscript b90faaf03 Avoid out of bounds array subscript 7d418492e Merge pull request #94 from nigels-com/proto2 015f9cc5e Specify proto2 syntax to appease protoc 23d48fd2a Use universal initialization syntax in constructors. 0f610fad5 Update travis config: Use xenial for most builds. d71da0b04 Update appveyor config: Simpler builds, current MSVC, 32bit build 3ef46ba78 Release 1.6.4 3a1ef0138 Tighten some tests. 18eebb8c3 Remove unused code from tests. 29ef3e4e7 More casts to remove undefined behaviour. 6108e6480 No more bitwise operations on signed integers in zigzag encoder/decoder. 6e0d34985 Remove bitwise operations on signed integers in varint decoder. 4af65f262 Update change log. 2f82182fe Add some tips to test/create_pbf_test_data.sh. c55f4ed55 Fix some doxygen warnings. afa362a03 Add static_asserts to check movability of some classes. efeb45e0c Disable readability-implicit-bool-conversion clang-tidy warning. 78febda5b Explicit conversion and tests for new pbf_reader::data() function. 0d5492c9c Revert "Explicit conversion and tests for new pbf_reader::data() function." 43cf8fa5a Fix travis config. bd2ae4682 Explicit conversion and tests for new pbf_reader::data() function. 28cd406bd Update travis with newer compiler versions. 0555e6a1f Add function to get the not yet read data from a pbf_reader. bf4284bee Disable docker builds on travis. They are being phased out by travis. 5ffe45b71 New add_packed_fixed template function. e54cd858d Add helper function that computes the length a varint would have. 72d7e143a More consistent implementation of operators. 3a41880c2 Do not download protobuf library, it isn't found by cmake anyway. 3c662ce3c Remove comment that doesn't apply (any more). 45da6dd4d Update zigzag tests. 4ad573dbf Extra cast so we do the xor with unsigned ints. 509aec5ab Update appveyor build to current Visual Studio compiler. 67b24e1a3 Remove unnecessary workaround in Appveyor config. c559af682 Remove xcode6.4 build soon to be removed from travis. 0662dcecc Release 1.6.3 da5bfc019 Move byteswap_inplace functions from detail into protozero namespace. a44efc34e Travis: Ignore install problems on OSX. 5775b2b23 Travis update to newer OSX image. 032aa037c Special case the distance between default initialized iterators. 0ca02161e Make dereferencing operator of fixed_iterator noexcept. a0095f603 Test code must call functions that it wants to test. 6791b0bc3 Add unit tests. 191eb4004 Add some paranoia asserts. 99ca512f5 Use TEST_CASEs instead of SECTIOs in some tests. 040e2bc14 Add some asserts and tests. git-subtree-dir: third_party/protozero git-subtree-split: f379578a3f7c8162aac0ac31c2696de09a5b5f93
This commit is contained in:
parent
68019a1fb2
commit
563c04ae2a
49
.clang-tidy
49
.clang-tidy
@ -1,14 +1,43 @@
|
||||
---
|
||||
Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-reinterpret-cast,-fuchsia-*,-google-runtime-references,-hicpp-no-array-decay'
|
||||
Checks: '*,-altera-*,-bugprone-easily-swappable-parameters,-bugprone-signed-char-misuse,-cert-dcl21-cpp,-cert-err58-cpp,-cert-err60-cpp,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-macro-usage,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-type-reinterpret-cast,-fuchsia-*,-google-runtime-references,-hicpp-avoid-c-arrays,-hicpp-no-array-decay,-hicpp-vararg,-llvmlibc-*,-misc-no-recursion,-modernize-avoid-c-arrays,-modernize-use-trailing-return-type,-readability-function-cognitive-complexity,-readability-identifier-length,-readability-implicit-bool-conversion,-readability-magic-numbers'
|
||||
#
|
||||
# Disabled checks:
|
||||
#
|
||||
# altera-*
|
||||
# Doesn't apply.
|
||||
#
|
||||
# bugprone-easily-swappable-parameters
|
||||
# Can't change this any more, because these functions are part of our public
|
||||
# interface.
|
||||
#
|
||||
# bugprone-signed-char-misuse
|
||||
# Lots of warnings in varint.hpp otherwise.
|
||||
#
|
||||
# cert-dcl21-cpp
|
||||
# It is unclear whether this is still a good recommendation in modern C++.
|
||||
#
|
||||
# cert-err58-cpp
|
||||
# Due to the Catch2 test framework.
|
||||
#
|
||||
# cert-err60-cpp
|
||||
# Reports std::runtime_error as broken which we can't do anything about.
|
||||
#
|
||||
# cppcoreguidelines-avoid-c-arrays
|
||||
# hicpp-avoid-c-arrays
|
||||
# modernize-avoid-c-arrays
|
||||
# Makes sense for some array, but especially for char arrays using
|
||||
# std::array isn't a good solution.
|
||||
#
|
||||
# cppcoreguidelines-avoid-magic-numbers
|
||||
# readability-magic-numbers
|
||||
# Good idea, but it goes too far to force this everywhere.
|
||||
#
|
||||
# cppcoreguidelines-avoid-non-const-global-variables
|
||||
# Getting these from Catch2 test framework, not from the code itself.
|
||||
#
|
||||
# cppcoreguidelines-macro-usage
|
||||
# There are cases where macros are simply needed.
|
||||
#
|
||||
# cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
||||
# Limited use and many false positives including for all asserts.
|
||||
#
|
||||
@ -28,6 +57,24 @@ Checks: '*,-cert-dcl21-cpp,-cert-err60-cpp,-cppcoreguidelines-pro-bounds-pointer
|
||||
# hicpp-no-array-decay
|
||||
# Limited use and many false positives including for all asserts.
|
||||
#
|
||||
# llvmlibc-*
|
||||
# Doesn't apply.
|
||||
#
|
||||
# misc-no-recursion
|
||||
# Nothing wrong with recursion.
|
||||
#
|
||||
# modernize-use-trailing-return-type
|
||||
# We are not quite that modern.
|
||||
#
|
||||
# readability-function-cognitive-complexity
|
||||
# Getting these mostly from Catch2 test framework.
|
||||
#
|
||||
# readability-identifier-length
|
||||
# Short identifiers do make sense sometimes.
|
||||
#
|
||||
# readability-implicit-bool-conversion
|
||||
# Not necessarily more readable.
|
||||
#
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '\/include\/'
|
||||
AnalyzeTemporaryDtors: false
|
||||
|
10
.github/actions/build-windows/action.yml
vendored
Normal file
10
.github/actions/build-windows/action.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: Build on Windows
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Build
|
||||
run: cmake --build . --config Release --verbose
|
||||
shell: bash
|
||||
working-directory: build
|
||||
|
10
.github/actions/build/action.yml
vendored
Normal file
10
.github/actions/build/action.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: Build
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Build
|
||||
run: make VERBOSE=1
|
||||
shell: bash
|
||||
working-directory: build
|
||||
|
12
.github/actions/cmake-windows/action.yml
vendored
Normal file
12
.github/actions/cmake-windows/action.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
name: CMake on Windows
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Create build directory
|
||||
run: mkdir build
|
||||
shell: bash
|
||||
- name: Configure
|
||||
run: cmake -LA .. -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
shell: bash
|
||||
working-directory: build
|
16
.github/actions/cmake/action.yml
vendored
Normal file
16
.github/actions/cmake/action.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
name: CMake
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Create build directory
|
||||
run: mkdir build
|
||||
shell: bash
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -LA .. \
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
|
||||
-DPROTOZERO_DATA_VIEW=${PROTOZERO_DATA_VIEW} \
|
||||
-DCMAKE_CXX_STANDARD=${CPP_VERSION}
|
||||
shell: bash
|
||||
working-directory: build
|
10
.github/actions/ctest-windows/action.yml
vendored
Normal file
10
.github/actions/ctest-windows/action.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: Test on Windows
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Test
|
||||
run: ctest --output-on-failure -C Release
|
||||
shell: bash
|
||||
working-directory: build
|
||||
|
10
.github/actions/ctest/action.yml
vendored
Normal file
10
.github/actions/ctest/action.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
name: Test
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Test
|
||||
run: ctest --output-on-failure
|
||||
shell: bash
|
||||
working-directory: build
|
||||
|
14
.github/actions/install-ubuntu/action.yml
vendored
Normal file
14
.github/actions/install-ubuntu/action.yml
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
name: Install Prerequisites on Ubuntu
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
|
||||
steps:
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -yq \
|
||||
libprotobuf-dev \
|
||||
protobuf-compiler
|
||||
if [ "$CC" = clang-13 ]; then sudo apt-get install -yq --no-install-suggests --no-install-recommends clang-13; fi
|
||||
shell: bash
|
176
.github/workflows/ci.yml
vendored
Normal file
176
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
name: CI
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
image:
|
||||
- "ubuntu:18.04" # gcc 7.5.0, clang 6.0.0, cmake 3.10.2
|
||||
- "ubuntu:20.04" # gcc 9.3.0, clang 10.0.0, cmake 3.16.3
|
||||
- "ubuntu:21.04" # gcc 10.3.0, clang 12.0.0, cmake 3.18.4
|
||||
- "ubuntu:21.10" # gcc 11.2.0, clang 13.0.0, cmake 3.18.4
|
||||
- "debian:stretch" # gcc 6.3.0, clang 3.8.1, cmake 3.7.2
|
||||
- "debian:buster" # gcc 8.3.0, clang 7.0.1, cmake 3.13.4
|
||||
- "debian:bullseye" # gcc 10.2.1, clang 11.0.1, cmake 3.18.4
|
||||
- "debian:testing" # gcc 10.3.0, clang 11.1.0, cmake 3.21.3
|
||||
- "debian:experimental" # gcc 11.0.0, clang 14.0.0, cmake 3.21.3
|
||||
- "fedora:34" # gcc 11.2.1, clang 12.0.1, cmake 3.20.5
|
||||
- "fedora:35" # gcc 11.2.1, clang 13.0.0, cmake 3.22.0
|
||||
build_type: [Debug]
|
||||
cpp_compiler: [g++]
|
||||
cpp_version: [11]
|
||||
include:
|
||||
- image: "debian:bullseye"
|
||||
cpp_version: 14
|
||||
- image: "debian:bullseye"
|
||||
cpp_version: 17
|
||||
- image: "debian:bullseye"
|
||||
cpp_version: 20
|
||||
- image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: 14
|
||||
- image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: 17
|
||||
- image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
cpp_version: 20
|
||||
- image: "debian:bullseye"
|
||||
build_type: Release
|
||||
- image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
- image: "debian:bullseye"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
data_view: std::string_view
|
||||
# Disabled because it fails due to a bug in the protobuf library
|
||||
# See https://github.com/protocolbuffers/protobuf/issues/7224
|
||||
# - image: "debian:bullseye"
|
||||
# c_compiler: clang
|
||||
# cpp_compiler: clang++
|
||||
# CXXFLAGS: "-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
# LDFLAGS: "-fsanitize=address,undefined,integer"
|
||||
- image: "debian:testing"
|
||||
c_compiler: clang
|
||||
cpp_compiler: clang++
|
||||
- image: "debian:experimental"
|
||||
c_compiler: clang-14
|
||||
cpp_compiler: clang++-14
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
env:
|
||||
BUILD_TYPE: ${{ matrix.build_type }}
|
||||
CC: ${{ matrix.c_compiler }}
|
||||
CXX: ${{ matrix.cpp_compiler }}
|
||||
CXXFLAGS: ${{ matrix.CXXFLAGS }}
|
||||
LDFLAGS: ${{ matrix.LDFLAGS }}
|
||||
CPP_VERSION: ${{ matrix.cpp_version }}
|
||||
PROTOZERO_DATA_VIEW: ${{ matrix.data_view }}
|
||||
APT_LISTCHANGES_FRONTEND: none
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
steps:
|
||||
- name: Prepare container (apt)
|
||||
shell: bash
|
||||
if: startsWith(matrix.image, 'debian:') || startsWith(matrix.image, 'ubuntu:')
|
||||
run: |
|
||||
apt-get update -qq
|
||||
apt-get install -y \
|
||||
clang \
|
||||
cmake \
|
||||
doxygen \
|
||||
g++ \
|
||||
graphviz \
|
||||
libprotobuf-dev \
|
||||
make \
|
||||
protobuf-compiler
|
||||
- name: Install compiler
|
||||
shell: bash
|
||||
if: matrix.cpp_compiler == 'clang++-14'
|
||||
run: apt-get install -y --no-install-suggests --no-install-recommends clang-14
|
||||
- name: Prepare container (dnf)
|
||||
shell: bash
|
||||
if: startsWith(matrix.image, 'fedora:')
|
||||
run: |
|
||||
dnf install --quiet --assumeyes \
|
||||
cmake \
|
||||
doxygen \
|
||||
gcc-c++ \
|
||||
graphviz \
|
||||
make \
|
||||
protobuf-devel \
|
||||
protobuf-lite-static
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/cmake
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
ubuntu-latest:
|
||||
runs-on: ubuntu-20.04
|
||||
env:
|
||||
CC: clang-13
|
||||
CXX: clang++-13
|
||||
BUILD_TYPE: Debug
|
||||
steps:
|
||||
- name: Install new clang
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main'
|
||||
shell: bash
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/install-ubuntu
|
||||
- uses: ./.github/actions/cmake
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
macos:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- "macos-10.15"
|
||||
- "macos-11.0"
|
||||
build_type: [Debug]
|
||||
include:
|
||||
- os: "macos-11.0"
|
||||
build_type: Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
BUILD_TYPE: ${{ matrix.build_type }}
|
||||
steps:
|
||||
- run: brew install protobuf
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ./.github/actions/cmake
|
||||
- uses: ./.github/actions/build
|
||||
- uses: ./.github/actions/ctest
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- windows-2019
|
||||
- windows-2022
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- run: |
|
||||
vcpkg install \
|
||||
protobuf:x64-windows \
|
||||
protobuf-c:x64-windows
|
||||
shell: bash
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/actions/cmake-windows
|
||||
- uses: ./.github/actions/build-windows
|
||||
- uses: ./.github/actions/ctest-windows
|
||||
|
252
.travis.yml
252
.travis.yml
@ -6,10 +6,6 @@
|
||||
|
||||
language: generic
|
||||
|
||||
sudo: false
|
||||
|
||||
dist: trusty
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Save common build configurations as shortcuts, so we can reference them later.
|
||||
@ -17,147 +13,265 @@ addons_shortcuts:
|
||||
addons_clang35: &clang35
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-3.5' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'clang-3.5' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-3.5' ]
|
||||
addons_clang38: &clang38
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-3.8' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'clang-3.8' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-3.8' ]
|
||||
addons_clang39: &clang39
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-3.9' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'clang-3.9' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-3.9' ]
|
||||
addons_clang40: &clang40
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-4.0' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'clang-4.0' ]
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-4.0' ]
|
||||
addons_clang50: &clang50
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-5.0' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'clang-5.0', 'clang-tidy-5.0' ]
|
||||
addons_gcc47: &gcc47
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-5.0' ]
|
||||
addons_clang60: &clang60
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-4.7', 'gcc-4.7' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-6.0' ]
|
||||
addons_clang7: &clang7
|
||||
apt:
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-7' ]
|
||||
addons_clang8: &clang8
|
||||
apt:
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-8' ]
|
||||
addons_clang9: &clang9
|
||||
apt:
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'clang-9', 'clang-tidy-9' ]
|
||||
addons_gcc48: &gcc48
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-4.8', 'gcc-4.8' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'g++-4.8', 'gcc-4.8' ]
|
||||
addons_gcc49: &gcc49
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-4.9', 'gcc-4.9' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'g++-4.9', 'gcc-4.9' ]
|
||||
addons_gcc5: &gcc5
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-5', 'gcc-5' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'g++-5', 'gcc-5' ]
|
||||
addons_gcc6: &gcc6
|
||||
apt:
|
||||
sources: [ 'ubuntu-toolchain-r-test' ]
|
||||
packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-6', 'gcc-6' ]
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'g++-6', 'gcc-6' ]
|
||||
addons_gcc7: &gcc7
|
||||
apt:
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler' ]
|
||||
addons_gcc8: &gcc8
|
||||
apt:
|
||||
packages: [ 'libprotobuf-dev', 'protobuf-compiler', 'g++-8', 'gcc-8' ]
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
matrix:
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: "clang-3.5"
|
||||
env: BUILD='Debug' CC=clang-3.5 CXX=clang++-3.5
|
||||
env: BUILD=Debug CC=clang-3.5 CXX=clang++-3.5
|
||||
addons: *clang35
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "clang-3.8"
|
||||
env: BUILD='Debug' CC=clang-3.8 CXX=clang++-3.8
|
||||
env: BUILD=Debug CC=clang-3.8 CXX=clang++-3.8
|
||||
addons: *clang38
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "clang-3.9"
|
||||
env: BUILD='Debug' CC=clang-3.9 CXX=clang++-3.9
|
||||
env: BUILD=Debug CC=clang-3.9 CXX=clang++-3.9
|
||||
addons: *clang39
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "clang-4.0"
|
||||
env: BUILD='Debug' CC=clang-4.0 CXX=clang++-4.0
|
||||
env: BUILD=Debug CC=clang-4.0 CXX=clang++-4.0
|
||||
addons: *clang40
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "clang-5.0"
|
||||
env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0
|
||||
CLANG_TIDY=clang-tidy-5.0
|
||||
env: BUILD=Debug CC=clang-5.0 CXX=clang++-5.0
|
||||
addons: *clang50
|
||||
|
||||
- os: linux
|
||||
compiler: "clang-5.0"
|
||||
env: BUILD='Release' CC=clang-5.0 CXX=clang++-5.0
|
||||
addons: *clang50
|
||||
dist: xenial
|
||||
compiler: "clang-6.0"
|
||||
env: BUILD=Debug CC=clang-6.0 CXX=clang++-6.0
|
||||
addons: *clang60
|
||||
|
||||
- os: linux
|
||||
compiler: "clang-5.0"
|
||||
env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0
|
||||
dist: bionic
|
||||
compiler: "clang-7"
|
||||
env: BUILD=Debug CC=clang-7 CXX=clang++-7
|
||||
addons: *clang7
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "clang-8"
|
||||
env: BUILD=Debug CC=clang-8 CXX=clang++-8
|
||||
addons: *clang8
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Debug CC=clang-9 CXX=clang++-9
|
||||
CLANG_TIDY=clang-tidy-9
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Debug CC=clang-9 CXX=clang++-9
|
||||
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
LDFLAGS="-fsanitize=address,undefined,integer"
|
||||
# LSAN doesn't work on container-based system
|
||||
sudo: required
|
||||
addons: *clang50
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-4.7"
|
||||
env: BUILD='Debug' CC=gcc-4.7 CXX=g++-4.7
|
||||
addons: *gcc47
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Release CC=clang-9 CXX=clang++-9
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Debug CC=clang-9 CXX=clang++-9
|
||||
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
LDFLAGS="-fsanitize=address,undefined,integer"
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Debug CC=clang-9 CXX=clang++-9
|
||||
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
LDFLAGS="-fsanitize=address,undefined,integer"
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
compiler: "clang-9"
|
||||
env: BUILD=Debug CC=clang-9 CXX=clang++-9
|
||||
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
LDFLAGS="-fsanitize=address,undefined,integer"
|
||||
addons: *clang9
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: "gcc-4.8"
|
||||
env: BUILD='Debug' CC=gcc-4.8 CXX=g++-4.8
|
||||
env: BUILD=Debug CC=gcc-4.8 CXX=g++-4.8
|
||||
addons: *gcc48
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: "gcc-4.9"
|
||||
env: BUILD='Debug' CC=gcc-4.9 CXX=g++-4.9
|
||||
COVERAGE=gcov-4.9
|
||||
CXXFLAGS="--coverage" LDFLAGS="--coverage"
|
||||
env: BUILD=Debug CC=gcc-4.9 CXX=g++-4.9
|
||||
addons: *gcc49
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: "gcc-5"
|
||||
env: BUILD='Debug' CC=gcc-5 CXX=g++-5
|
||||
env: BUILD=Debug CC=gcc-5 CXX=g++-5
|
||||
CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0"
|
||||
addons: *gcc5
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "gcc-5"
|
||||
env: BUILD='Debug' CC=gcc-5 CXX=g++-5
|
||||
env: BUILD=Debug CC=gcc-5 CXX=g++-5
|
||||
CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1"
|
||||
addons: *gcc5
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: "gcc-6"
|
||||
env: BUILD='Debug' CC=gcc-6 CXX=g++-6
|
||||
env: BUILD=Debug CC=gcc-6 CXX=g++-6
|
||||
addons: *gcc6
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-6"
|
||||
env: BUILD='Debug' CC=gcc-6 CXX=g++-6
|
||||
PROTOZERO_DATA_VIEW=std::experimental::string_view
|
||||
addons: *gcc6
|
||||
dist: bionic
|
||||
compiler: "gcc-7"
|
||||
env: BUILD=Debug CC=gcc-7 CXX=g++-7
|
||||
addons: *gcc7
|
||||
|
||||
- os: linux
|
||||
compiler: "gcc-6"
|
||||
env: BUILD='Release' CC=gcc-6 CXX=g++-6
|
||||
addons: *gcc6
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
COVERAGE=gcov-8
|
||||
CXXFLAGS="--coverage" LDFLAGS="--coverage"
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
PROTOZERO_DATA_VIEW=std::string_view
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Release CC=gcc-8 CXX=g++-8
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
addons: *gcc8
|
||||
|
||||
- os: linux
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
compiler: "gcc-8"
|
||||
env: BUILD=Debug CC=gcc-8 CXX=g++-8
|
||||
addons: *gcc8
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
osx_image: xcode9.4
|
||||
compiler: clang
|
||||
env: BUILD='Debug'
|
||||
env: BUILD=Debug
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode10.3
|
||||
compiler: clang
|
||||
env: BUILD='Debug'
|
||||
env: BUILD=Debug
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
osx_image: xcode11.4
|
||||
compiler: clang
|
||||
env: BUILD='Debug'
|
||||
env: BUILD=Debug
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
osx_image: xcode11.4
|
||||
compiler: clang
|
||||
env: BUILD='Debug'
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
compiler: clang
|
||||
env: BUILD='Release'
|
||||
env: BUILD=Release
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
install:
|
||||
- if [[ $(uname -s) == 'Darwin' ]]; then
|
||||
brew update;
|
||||
brew install protobuf;
|
||||
fi
|
||||
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
|
114
CHANGELOG.md
114
CHANGELOG.md
@ -2,9 +2,8 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/)
|
||||
This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [unreleased] -
|
||||
|
||||
@ -15,6 +14,105 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
### Fixed
|
||||
|
||||
|
||||
## [1.7.1] - 2022-01-10
|
||||
|
||||
### Changed
|
||||
|
||||
- Don't build tests if the standard CMake `BUILD_TESTING` variable is set to
|
||||
off.
|
||||
- Now needs CMake 3.5.0 or greater.
|
||||
- Update included catch2 framework to current version v2.13.8.
|
||||
- Only enable clang-tidy make target if protobuf was found.
|
||||
- Allow setting C++ version to compile with in CMake config.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixes undefined behaviour in `float` and `double` byteswap.
|
||||
- Add missing includes of "config.hpp".
|
||||
- Avoid narrowing conversion by doing an explicit `static_cast`.
|
||||
|
||||
|
||||
## [1.7.0] - 2020-06-08
|
||||
|
||||
### Added
|
||||
|
||||
- Support for buffer types other that `std::string`. `pbf_writer` is now
|
||||
just a typedef for `basic_pbf_writer<std::string>`. Other buffer types
|
||||
can be used with `basic_pbf_writer`. See `doc/advanced.md` for details.
|
||||
|
||||
### Changed
|
||||
|
||||
- Switched to *catch2* for testing.
|
||||
- Some minor tweaks.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Removed some undefined behaviour.
|
||||
|
||||
|
||||
## [1.6.8] - 2019-08-15
|
||||
|
||||
### Changed
|
||||
|
||||
- Various code cleanups due to clang-tidy warnings.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Made `data_view::compare` noexcept.
|
||||
|
||||
|
||||
## [1.6.7] - 2018-02-21
|
||||
|
||||
### Fixed
|
||||
|
||||
- Signed-unsigned comparison on 32 bit systems.
|
||||
|
||||
|
||||
## [1.6.6] - 2018-02-20
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed several place with possible undefined behaviour.
|
||||
|
||||
|
||||
## [1.6.5] - 2018-02-05
|
||||
|
||||
### Fixed
|
||||
|
||||
- Avoid UB: Do not calculate pointer outside array bounds.
|
||||
- Specify proto2 syntax in .proto files to appease protoc.
|
||||
|
||||
|
||||
## [1.6.4] - 2018-11-08
|
||||
|
||||
### Added
|
||||
|
||||
- Add function `data()` to get the not yet read data from a `pbf_reader`.
|
||||
- New `add_packed_fixed()` template function for `pbf_writer`.
|
||||
- New `length_of_varint()` helper function calculates how long a varint
|
||||
would be for a specified value.
|
||||
|
||||
### Changed
|
||||
|
||||
- More consistent implementation of operators as free friend functions.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed some zigzag encoding tests on MSVC.
|
||||
- Add extra cast so we do an xor with unsigned ints.
|
||||
- No more bitwise operations on signed integers in varint decoder.
|
||||
- No more bitwise operations on signed integers in zigzag encoder/decoder.
|
||||
|
||||
|
||||
## [1.6.3] - 2018-07-17
|
||||
|
||||
### Changed
|
||||
|
||||
- Moved `byteswap_inplace` functions from detail into protozero namespace.
|
||||
They can be useful outsize protozero.
|
||||
- More asserts and unit tests and small cleanups.
|
||||
|
||||
|
||||
## [1.6.2] - 2018-03-09
|
||||
|
||||
### Changed
|
||||
@ -301,7 +399,15 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Make pbf reader and writer code endianess-aware.
|
||||
|
||||
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v1.6.2...HEAD
|
||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v1.7.1...HEAD
|
||||
[1.7.1]: https://github.com/osmcode/libosmium/compare/v1.7.0...v1.7.1
|
||||
[1.7.0]: https://github.com/osmcode/libosmium/compare/v1.6.8...v1.7.0
|
||||
[1.6.8]: https://github.com/osmcode/libosmium/compare/v1.6.7...v1.6.8
|
||||
[1.6.7]: https://github.com/osmcode/libosmium/compare/v1.6.6...v1.6.7
|
||||
[1.6.6]: https://github.com/osmcode/libosmium/compare/v1.6.5...v1.6.6
|
||||
[1.6.5]: https://github.com/osmcode/libosmium/compare/v1.6.4...v1.6.5
|
||||
[1.6.4]: https://github.com/osmcode/libosmium/compare/v1.6.3...v1.6.4
|
||||
[1.6.3]: https://github.com/osmcode/libosmium/compare/v1.6.2...v1.6.3
|
||||
[1.6.2]: https://github.com/osmcode/libosmium/compare/v1.6.1...v1.6.2
|
||||
[1.6.1]: https://github.com/osmcode/libosmium/compare/v1.6.0...v1.6.1
|
||||
[1.6.0]: https://github.com/osmcode/libosmium/compare/v1.5.3...v1.6.0
|
||||
|
@ -6,32 +6,35 @@
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.5.0 FATAL_ERROR)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
project(protozero)
|
||||
|
||||
set(PROTOZERO_VERSION_MAJOR 1)
|
||||
set(PROTOZERO_VERSION_MINOR 6)
|
||||
set(PROTOZERO_VERSION_PATCH 2)
|
||||
|
||||
set(PROTOZERO_VERSION
|
||||
"${PROTOZERO_VERSION_MAJOR}.${PROTOZERO_VERSION_MINOR}.${PROTOZERO_VERSION_PATCH}")
|
||||
project(protozero VERSION 1.7.1 LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
if (NOT "${CMAKE_CXX_STANDARD}")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
message(STATUS "Building in C++${CMAKE_CXX_STANDARD} mode")
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
option(BUILD_TESTING "Build tests" ON)
|
||||
option(WERROR "Add -Werror flag to build (turns warnings into errors)" ON)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-std=c++11 /W3)
|
||||
add_compile_options(/W3)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS)
|
||||
else()
|
||||
add_definitions(-std=c++11 -Wall -Wextra -pedantic -Wsign-compare -Wunused-parameter -Wno-float-equal -Wno-covered-switch-default)
|
||||
add_compile_options(-Wall -Wextra -pedantic -Wsign-compare -Wunused-parameter -Wno-float-equal -Wno-covered-switch-default)
|
||||
if(WERROR)
|
||||
add_definitions(-Werror)
|
||||
add_compile_options(-Werror)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -58,15 +61,16 @@ find_package(Protobuf)
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
message(STATUS "Looking for clang-tidy")
|
||||
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0 clang-tidy-5.0)
|
||||
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11)
|
||||
|
||||
if(CLANG_TIDY)
|
||||
if(CLANG_TIDY AND PROTOBUF_FOUND)
|
||||
message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}")
|
||||
add_custom_target(clang-tidy
|
||||
${CLANG_TIDY}
|
||||
-p ${CMAKE_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/test/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/t/*/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/t/*/reader_test_cases.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/t/*/writer_test_cases.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/unit/*.cpp
|
||||
${CMAKE_SOURCE_DIR}/tools/*.cpp
|
||||
)
|
||||
@ -133,13 +137,13 @@ install(DIRECTORY include/protozero DESTINATION include)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_subdirectory(doc)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
add_subdirectory(tools)
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
To do fuzz testing using [AFL](http://lcamtuf.coredump.cx/afl/) compile with
|
||||
To do fuzz testing using [AFL](https://lcamtuf.coredump.cx/afl/) compile with
|
||||
the AFL compiler wrappers:
|
||||
|
||||
mkdir build
|
||||
|
10
README.md
10
README.md
@ -11,7 +11,7 @@ changing frequently or lazy decoding is not critical for your application then
|
||||
this approach offers no value: just use the C++ API that can be generated with
|
||||
the Google Protobufs `protoc` program.
|
||||
|
||||
[](https://travis-ci.org/mapbox/protozero)
|
||||
[](https://travis-ci.com/mapbox/protozero)
|
||||
[](https://ci.appveyor.com/project/Mapbox/protozero)
|
||||
[](https://codecov.io/gh/mapbox/protozero)
|
||||
[](https://repology.org/metapackage/protozero)
|
||||
@ -56,9 +56,9 @@ You have to have a working knowledge of how
|
||||
* Read the [upgrading instructions](UPGRADING.md) if you are upgrading from
|
||||
an older version of Protozero.
|
||||
|
||||
The build process will also build the Doxygen-based reference documentation
|
||||
if you have [Doxygen](http://www.stack.nl/~dimitri/doxygen/) installed. Then
|
||||
open `doc/html/index.html` in your browser to read it.
|
||||
The build process will also build the Doxygen-based reference documentation if
|
||||
you have Doxygen installed. Then open `doc/html/index.html` in your browser to
|
||||
read it.
|
||||
|
||||
|
||||
## Endianness
|
||||
@ -123,7 +123,7 @@ You might have to set `CLANG_TIDY` in CMake config.
|
||||
|
||||
## Cppcheck
|
||||
|
||||
For extra checks with [Cppcheck](http://cppcheck.sourceforge.net/) you can,
|
||||
For extra checks with [Cppcheck](https://cppcheck.sourceforge.io/) you can,
|
||||
after the CMake step, call
|
||||
|
||||
make cppcheck
|
||||
|
@ -13,6 +13,11 @@ macro `PROTOZERO_STRICT_API` in which case Protozero will compile without the
|
||||
code used for backwards compatibilty. You will then get compile errors for
|
||||
older API usages.
|
||||
|
||||
## Upgrading from *v1.6* to *v1.7*
|
||||
|
||||
* The `pbf_writer` class is now a typedef for `basic_pbf_writer<std::string>`
|
||||
If you have forward declared it in your code, it might have to change.
|
||||
|
||||
## Upgrading from *v1.5* to *v1.6.0*
|
||||
|
||||
* The `data_view` class moved from `types.hpp` into its own header file
|
||||
|
52
appveyor.yml
52
appveyor.yml
@ -14,16 +14,20 @@ clone_depth: 1
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- config: Debug
|
||||
autocrlf: true
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: true
|
||||
- config: Debug
|
||||
autocrlf: false
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: false
|
||||
- config: Debug
|
||||
autocrlf: false
|
||||
platform: x86
|
||||
- config: MSYS2
|
||||
autocrlf: true
|
||||
- config: Debug
|
||||
autocrlf: true
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: true
|
||||
- config: Debug
|
||||
autocrlf: false
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: false
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@ -36,22 +40,32 @@ init:
|
||||
# halts: "msys2-runtime and catgets are in conflict. Remove catgets?"
|
||||
# See also: https://github.com/Alexpux/MSYS2-packages/issues/1141
|
||||
install:
|
||||
- if [%config%]==[MSYS2] (
|
||||
C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh --sysupgrade --sysupgrade --ask=20
|
||||
&& C:\msys64\usr\bin\pacman -Rc --noconfirm mingw-w64-x86_64-gcc-libs
|
||||
- if "%config%"=="MSYS2" (
|
||||
set "PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH%" &&
|
||||
pacman --noconfirm --sync --refresh --refresh --sysupgrade --sysupgrade --ask=20 &&
|
||||
pacman -Rc --noconfirm mingw-w64-x86_64-gcc-libs &&
|
||||
pacman -S --needed --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-doxygen mingw-w64-x86_64-protobuf
|
||||
)
|
||||
|
||||
build_script:
|
||||
- if [%config%]==[MSYS2] (
|
||||
build-msys2.bat
|
||||
- cd c:\projects\protozero
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if "%platform%"=="x64" (
|
||||
set vcvarsall_arg=amd64
|
||||
) else (
|
||||
build-appveyor.bat
|
||||
set vcvarsall_arg=x86
|
||||
)
|
||||
- if "%config%"=="MSYS2" (
|
||||
cmake .. -LA -G "MSYS Makefiles" &&
|
||||
make VERBOSE=1
|
||||
) else (
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall" %vcvarsall_arg% &&
|
||||
cmake .. -LA -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%config% &&
|
||||
nmake VERBOSE=1
|
||||
)
|
||||
|
||||
# remove garbage VS messages
|
||||
# http://help.appveyor.com/discussions/problems/4569-the-target-_convertpdbfiles-listed-in-a-beforetargets-attribute-at-c-does-not-exist-in-the-project-and-will-be-ignored
|
||||
before_build:
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
||||
test_script:
|
||||
- ctest --output-on-failure
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
mapbox-streets-v6/14/8714/8017.vector.pbf
|
||||
|
||||
- http://c.tile.openstreetmap.org/14/8714/8017.png
|
||||
- https://c.tile.openstreetmap.org/14/8714/8017.png
|
||||
- https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/14/8714/8017.vector.pbf
|
||||
- https://www.mapbox.com/developers/vector-tiles/mapbox-streets/
|
||||
|
||||
@ -10,4 +10,4 @@ enf-14-4824-6157.vector.pbf
|
||||
|
||||
- enf.8k273nmi
|
||||
- https://b.tiles.mapbox.com/v4/enf.c3a2de35/14/4824/6157@2x.png
|
||||
- https://www.mapbox.com/blog/twitter-map-every-tweet/
|
||||
- https://www.mapbox.com/blog/twitter-map-every-tweet/
|
||||
|
@ -1,65 +0,0 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO ~~~~~~ %~f0 ~~~~~~
|
||||
|
||||
::show all available env vars
|
||||
SET
|
||||
ECHO cmake on AppVeyor
|
||||
cmake -version
|
||||
|
||||
ECHO activating VS cmd prompt && CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET protobuf_sdk=protozero-dep-protobuf-2.6.1.7z
|
||||
IF EXIST %protobuf_sdk% (ECHO protobuf already downloaded) ELSE (ECHO downloading protobuf ... && powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/$env:protobuf_sdk -OutFile $pwd\$env:protobuf_sdk)
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
IF EXIST deps\protobuf (ECHO protobuf already extracted) ELSE (CALL 7z x -y %protobuf_sdk% | %windir%\system32\FIND "ing archive")
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
SET PATH=%~dp0deps\protobuf;%PATH%
|
||||
|
||||
IF EXIST build ECHO deleting build dir... && RD /Q /S build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
MKDIR build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
CD build
|
||||
ECHO config^: %config%
|
||||
|
||||
::This will produce lots of LNK4099 warnings which can be ignored.
|
||||
::Unfortunately they can't be disabled, see
|
||||
::http://stackoverflow.com/questions/661606/visual-c-how-to-disable-specific-linker-warnings
|
||||
SET CMAKE_CMD=cmake .. ^
|
||||
-LA -G "Visual Studio 14 Win64"
|
||||
|
||||
ECHO calling^: %CMAKE_CMD%
|
||||
%CMAKE_CMD%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET avlogger=
|
||||
IF /I "%APPVEYOR%"=="True" SET avlogger=/logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
msbuild protozero.sln ^
|
||||
/p:Configuration=%config% ^
|
||||
/toolsversion:14.0 ^
|
||||
/p:Platform=x64 ^
|
||||
/p:PlatformToolset=v140 %avlogger%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ctest --output-on-failure ^
|
||||
-C %config% ^
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
GOTO DONE
|
||||
|
||||
:ERROR
|
||||
ECHO ~~~~~~ ERROR %~f0 ~~~~~~
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
IF %EL% NEQ 0 ECHO. && ECHO !!! ERRORLEVEL^: %EL% !!! && ECHO.
|
||||
ECHO ~~~~~~ DONE %~f0 ~~~~~~
|
||||
|
||||
EXIT /b %EL%
|
@ -1,29 +0,0 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO =========== %~f0 ===========
|
||||
|
||||
SET VERBOSITY_MSBUILD=diagnostic
|
||||
IF NOT "%1"=="" SET VERBOSITY_MSBUILD=%1
|
||||
SET platform=x64
|
||||
SET configuration=Release
|
||||
CALL build-appveyor.bat %VERBOSITY_MSBUILD%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET platform=x86
|
||||
SET configuration=Debug
|
||||
CALL build-appveyor.bat %VERBOSITY_MSBUILD%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
GOTO DONE
|
||||
|
||||
:ERROR
|
||||
ECHO =========== ERROR %~f0 ===========
|
||||
ECHO ERRORLEVEL^: %ERRORLEVEL%
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
ECHO =========== DONE %~f0 ===========
|
||||
|
||||
EXIT /b %EL%
|
@ -1,18 +0,0 @@
|
||||
echo "Adding MSYS2 to path..."
|
||||
SET "PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin;%PATH%"
|
||||
echo %PATH%
|
||||
|
||||
echo "Installing MSYS2 packages..."
|
||||
bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-doxygen mingw-w64-x86_64-protobuf"
|
||||
|
||||
echo "Generating makefiles"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -LA -G "MSYS Makefiles"
|
||||
|
||||
echo "Building"
|
||||
make VERBOSE=1
|
||||
|
||||
echo "Testing"
|
||||
ctest --output-on-failure
|
||||
|
705
doc/Doxyfile.in
705
doc/Doxyfile.in
File diff suppressed because it is too large
Load Diff
@ -269,3 +269,58 @@ still considerably cheaper than decoding the varints. You have to benchmark
|
||||
your use case to see whether the `reserve()` (or whatever you are using the
|
||||
`size()` for) is worth it.
|
||||
|
||||
|
||||
## Using a different buffer class than std::string
|
||||
|
||||
Normally you are using the `pbf_writer` or `pbf_builder` classes which use a
|
||||
`std::string` that you supply as their buffer for building the actual protocol
|
||||
buffers message into. But you can use a different buffer implementation
|
||||
instead. This might be useful if you want to use a fixed-size buffer for
|
||||
instance.
|
||||
|
||||
The `pbf_writer` and `pbf_builder` classes are actually only aliases for the
|
||||
`basic_pbf_writer` and `basic_pbf_builder` template classes:
|
||||
|
||||
```cpp
|
||||
using pbf_writer = basic_pbf_writer<std::string>;
|
||||
|
||||
template <typename T>
|
||||
using pbf_builder = basic_pbf_builder<std::string, T>;
|
||||
```
|
||||
|
||||
If you want to use a different buffer type, use the `basic_*` form of the
|
||||
class and use the buffer class as template parameter. When instantiating the
|
||||
`basic_pbf_writer` or `basic_pbf_builder`, the only parameter to the
|
||||
constructor must always be a reference to an object of the buffer class.
|
||||
|
||||
```cpp
|
||||
some_buffer_class buffer;
|
||||
basic_pbf_writer<some_buffer_class> writer{buffer};
|
||||
```
|
||||
|
||||
For this to work you must supply template specializations for some static
|
||||
functions in the `protozero::buffer_customization` struct, see
|
||||
`buffer_tmpl.hpp` for details.
|
||||
|
||||
Protozero already supports two buffer types:
|
||||
* `std::string` (to use include `protozero/buffer_string.hpp`)
|
||||
* `std::vector<char>` (to use include `protozero/buffer_vector.hpp`)
|
||||
|
||||
There is a class `protozero::fixed_size_buffer_adaptor` you can use as adaptor
|
||||
for any fixed-sized buffer you might have. Include `protozero/buffer_fixed.hpp`
|
||||
to use it:
|
||||
|
||||
```cpp
|
||||
#include <protozero/buffer_fixed.hpp>
|
||||
|
||||
your_buffer_class some_buffer;
|
||||
protozero::fixed_size_buffer_adaptor buffer_adaptor{some_buffer.data(), some_buffer.size()};
|
||||
basic_pbf_writer<protozero::fixed_size_buffer_adaptor> writer{buffer_adaptor};
|
||||
```
|
||||
|
||||
The buffer adaptor can be initialized with any container if it supports the
|
||||
`data()` and `size()` member functions:
|
||||
|
||||
```cpp
|
||||
protozero::fixed_size_buffer_adaptor buffer_adaptor{some_buffer};
|
||||
```
|
||||
|
266
include/protozero/basic_pbf_builder.hpp
Normal file
266
include/protozero/basic_pbf_builder.hpp
Normal file
@ -0,0 +1,266 @@
|
||||
#ifndef PROTOZERO_BASIC_PBF_BUILDER_HPP
|
||||
#define PROTOZERO_BASIC_PBF_BUILDER_HPP
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
protozero - Minimalistic protocol buffer decoder and encoder in C++.
|
||||
|
||||
This file is from https://github.com/mapbox/protozero where you can find more
|
||||
documentation.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file basic_pbf_builder.hpp
|
||||
*
|
||||
* @brief Contains the basic_pbf_builder template class.
|
||||
*/
|
||||
|
||||
#include "basic_pbf_writer.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
/**
|
||||
* The basic_pbf_builder is used to write PBF formatted messages into a buffer.
|
||||
* It is based on the basic_pbf_writer class and has all the same methods. The
|
||||
* difference is that while the pbf_writer class takes an integer tag,
|
||||
* this template class takes a tag of the template type T. The idea is that
|
||||
* T will be an enumeration value and this helps reduce the possibility of
|
||||
* programming errors.
|
||||
*
|
||||
* Almost all methods in this class can throw an std::bad_alloc exception if
|
||||
* the underlying buffer class wants to resize.
|
||||
*
|
||||
* Read the tutorial to understand how this class is used. In most cases you
|
||||
* want to use the pbf_builder class which uses a std::string as buffer type.
|
||||
*/
|
||||
template <typename TBuffer, typename T>
|
||||
class basic_pbf_builder : public basic_pbf_writer<TBuffer> {
|
||||
|
||||
static_assert(std::is_same<pbf_tag_type, typename std::underlying_type<T>::type>::value,
|
||||
"T must be enum with underlying type protozero::pbf_tag_type");
|
||||
|
||||
public:
|
||||
|
||||
/// The type of messages this class will build.
|
||||
using enum_type = T;
|
||||
|
||||
basic_pbf_builder() = default;
|
||||
|
||||
/**
|
||||
* Create a builder using the given string as a data store. The object
|
||||
* stores a reference to that string and adds all data to it. The string
|
||||
* doesn't have to be empty. The pbf_message object will just append data.
|
||||
*/
|
||||
explicit basic_pbf_builder(TBuffer& data) noexcept :
|
||||
basic_pbf_writer<TBuffer>{data} {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a pbf_builder for a submessage from the pbf_message or
|
||||
* pbf_writer of the parent message.
|
||||
*
|
||||
* @param parent_writer The parent pbf_message or pbf_writer
|
||||
* @param tag Tag of the field that will be written
|
||||
*/
|
||||
template <typename P>
|
||||
basic_pbf_builder(basic_pbf_writer<TBuffer>& parent_writer, P tag) noexcept :
|
||||
basic_pbf_writer<TBuffer>{parent_writer, pbf_tag_type(tag)} {
|
||||
}
|
||||
|
||||
/// @cond INTERNAL
|
||||
#define PROTOZERO_WRITER_WRAP_ADD_SCALAR(name, type) \
|
||||
void add_##name(T tag, type value) { \
|
||||
basic_pbf_writer<TBuffer>::add_##name(pbf_tag_type(tag), value); \
|
||||
}
|
||||
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(bool, bool)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(enum, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(int32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sint32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(uint32, uint32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(int64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sint64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(uint64, uint64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(fixed32, uint32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sfixed32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(fixed64, uint64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sfixed64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(float, float)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(double, double)
|
||||
|
||||
#undef PROTOZERO_WRITER_WRAP_ADD_SCALAR
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
* @param size Number of bytes to be written
|
||||
*/
|
||||
void add_bytes(T tag, const char* value, std::size_t size) {
|
||||
basic_pbf_writer<TBuffer>::add_bytes(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const data_view& value) {
|
||||
basic_pbf_writer<TBuffer>::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const std::string& value) {
|
||||
basic_pbf_writer<TBuffer>::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data. Bytes from the value are written until
|
||||
* a null byte is encountered. The null byte is not added.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to zero-delimited value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const char* value) {
|
||||
basic_pbf_writer<TBuffer>::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data using vectored input. All the data in the
|
||||
* 2nd and further arguments is "concatenated" with only a single copy
|
||||
* into the final buffer.
|
||||
*
|
||||
* This will work with objects of any type supporting the data() and
|
||||
* size() methods like std::string or protozero::data_view.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* std::string data1 = "abc";
|
||||
* std::string data2 = "xyz";
|
||||
* builder.add_bytes_vectored(1, data1, data2);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam Ts List of types supporting data() and size() methods.
|
||||
* @param tag Tag of the field
|
||||
* @param values List of objects of types Ts with data to be appended.
|
||||
*/
|
||||
template <typename... Ts>
|
||||
void add_bytes_vectored(T tag, Ts&&... values) {
|
||||
basic_pbf_writer<TBuffer>::add_bytes_vectored(pbf_tag_type(tag), std::forward<Ts>(values)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
* @param size Number of bytes to be written
|
||||
*/
|
||||
void add_string(T tag, const char* value, std::size_t size) {
|
||||
basic_pbf_writer<TBuffer>::add_string(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_string(T tag, const data_view& value) {
|
||||
basic_pbf_writer<TBuffer>::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_string(T tag, const std::string& value) {
|
||||
basic_pbf_writer<TBuffer>::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data. Bytes from the value are written until
|
||||
* a null byte is encountered. The null byte is not added.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
*/
|
||||
void add_string(T tag, const char* value) {
|
||||
basic_pbf_writer<TBuffer>::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to message to be written
|
||||
* @param size Length of the message
|
||||
*/
|
||||
void add_message(T tag, const char* value, std::size_t size) {
|
||||
basic_pbf_writer<TBuffer>::add_message(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written. The value must be a complete message.
|
||||
*/
|
||||
void add_message(T tag, const data_view& value) {
|
||||
basic_pbf_writer<TBuffer>::add_message(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written. The value must be a complete message.
|
||||
*/
|
||||
void add_message(T tag, const std::string& value) {
|
||||
basic_pbf_writer<TBuffer>::add_message(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/// @cond INTERNAL
|
||||
#define PROTOZERO_WRITER_WRAP_ADD_PACKED(name) \
|
||||
template <typename InputIterator> \
|
||||
void add_packed_##name(T tag, InputIterator first, InputIterator last) { \
|
||||
basic_pbf_writer<TBuffer>::add_packed_##name(pbf_tag_type(tag), first, last); \
|
||||
}
|
||||
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(bool)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(enum)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(int32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sint32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(uint32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(int64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sint64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(uint64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(fixed32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sfixed32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(fixed64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sfixed64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(float)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(double)
|
||||
|
||||
#undef PROTOZERO_WRITER_WRAP_ADD_PACKED
|
||||
/// @endcond
|
||||
|
||||
}; // class basic_pbf_builder
|
||||
|
||||
} // end namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BASIC_PBF_BUILDER_HPP
|
1054
include/protozero/basic_pbf_writer.hpp
Normal file
1054
include/protozero/basic_pbf_writer.hpp
Normal file
File diff suppressed because it is too large
Load Diff
222
include/protozero/buffer_fixed.hpp
Normal file
222
include/protozero/buffer_fixed.hpp
Normal file
@ -0,0 +1,222 @@
|
||||
#ifndef PROTOZERO_BUFFER_FIXED_HPP
|
||||
#define PROTOZERO_BUFFER_FIXED_HPP
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
protozero - Minimalistic protocol buffer decoder and encoder in C++.
|
||||
|
||||
This file is from https://github.com/mapbox/protozero where you can find more
|
||||
documentation.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file buffer_fixed.hpp
|
||||
*
|
||||
* @brief Contains the fixed_size_buffer_adaptor class.
|
||||
*/
|
||||
|
||||
#include "buffer_tmpl.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
/**
|
||||
* This class can be used instead of std::string if you want to create a
|
||||
* vector tile in a fixed-size buffer. Any operation that needs more space
|
||||
* than is available will fail with a std::length_error exception.
|
||||
*/
|
||||
class fixed_size_buffer_adaptor {
|
||||
|
||||
char* m_data;
|
||||
std::size_t m_capacity;
|
||||
std::size_t m_size = 0;
|
||||
|
||||
public:
|
||||
|
||||
/// @cond usual container typedefs not documented
|
||||
|
||||
using size_type = std::size_t;
|
||||
|
||||
using value_type = char;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param data Pointer to some memory allocated for the buffer.
|
||||
* @param capacity Number of bytes available.
|
||||
*/
|
||||
fixed_size_buffer_adaptor(char* data, std::size_t capacity) noexcept :
|
||||
m_data(data),
|
||||
m_capacity(capacity) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param container Some container class supporting the member functions
|
||||
* data() and size().
|
||||
*/
|
||||
template <typename T>
|
||||
explicit fixed_size_buffer_adaptor(T& container) :
|
||||
m_data(container.data()),
|
||||
m_capacity(container.size()) {
|
||||
}
|
||||
|
||||
/// Returns a pointer to the data in the buffer.
|
||||
const char* data() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// Returns a pointer to the data in the buffer.
|
||||
char* data() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// The capacity this buffer was created with.
|
||||
std::size_t capacity() const noexcept {
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
/// The number of bytes used in the buffer. Always <= capacity().
|
||||
std::size_t size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/// Return iterator to beginning of data.
|
||||
char* begin() noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// Return iterator to beginning of data.
|
||||
const char* begin() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// Return iterator to beginning of data.
|
||||
const char* cbegin() const noexcept {
|
||||
return m_data;
|
||||
}
|
||||
|
||||
/// Return iterator to end of data.
|
||||
char* end() noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
/// Return iterator to end of data.
|
||||
const char* end() const noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
/// Return iterator to end of data.
|
||||
const char* cend() const noexcept {
|
||||
return m_data + m_size;
|
||||
}
|
||||
|
||||
/// @cond INTERNAL
|
||||
|
||||
// Do not rely on anything beyond this point
|
||||
|
||||
void append(const char* data, std::size_t count) {
|
||||
if (m_size + count > m_capacity) {
|
||||
throw std::length_error{"fixed size data store exhausted"};
|
||||
}
|
||||
std::copy_n(data, count, m_data + m_size);
|
||||
m_size += count;
|
||||
}
|
||||
|
||||
void append_zeros(std::size_t count) {
|
||||
if (m_size + count > m_capacity) {
|
||||
throw std::length_error{"fixed size data store exhausted"};
|
||||
}
|
||||
std::fill_n(m_data + m_size, count, '\0');
|
||||
m_size += count;
|
||||
}
|
||||
|
||||
void resize(std::size_t size) {
|
||||
protozero_assert(size < m_size);
|
||||
if (size > m_capacity) {
|
||||
throw std::length_error{"fixed size data store exhausted"};
|
||||
}
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void erase_range(std::size_t from, std::size_t to) {
|
||||
protozero_assert(from <= m_size);
|
||||
protozero_assert(to <= m_size);
|
||||
protozero_assert(from < to);
|
||||
std::copy(m_data + to, m_data + m_size, m_data + from);
|
||||
m_size -= (to - from);
|
||||
}
|
||||
|
||||
char* at_pos(std::size_t pos) {
|
||||
protozero_assert(pos <= m_size);
|
||||
return m_data + pos;
|
||||
}
|
||||
|
||||
void push_back(char ch) {
|
||||
if (m_size >= m_capacity) {
|
||||
throw std::length_error{"fixed size data store exhausted"};
|
||||
}
|
||||
m_data[m_size++] = ch;
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
}; // class fixed_size_buffer_adaptor
|
||||
|
||||
/// @cond INTERNAL
|
||||
template <>
|
||||
struct buffer_customization<fixed_size_buffer_adaptor> {
|
||||
|
||||
static std::size_t size(const fixed_size_buffer_adaptor* buffer) noexcept {
|
||||
return buffer->size();
|
||||
}
|
||||
|
||||
static void append(fixed_size_buffer_adaptor* buffer, const char* data, std::size_t count) {
|
||||
buffer->append(data, count);
|
||||
}
|
||||
|
||||
static void append_zeros(fixed_size_buffer_adaptor* buffer, std::size_t count) {
|
||||
buffer->append_zeros(count);
|
||||
}
|
||||
|
||||
static void resize(fixed_size_buffer_adaptor* buffer, std::size_t size) {
|
||||
buffer->resize(size);
|
||||
}
|
||||
|
||||
static void reserve_additional(fixed_size_buffer_adaptor* /*buffer*/, std::size_t /*size*/) {
|
||||
/* nothing to be done for fixed-size buffers */
|
||||
}
|
||||
|
||||
static void erase_range(fixed_size_buffer_adaptor* buffer, std::size_t from, std::size_t to) {
|
||||
buffer->erase_range(from, to);
|
||||
}
|
||||
|
||||
static char* at_pos(fixed_size_buffer_adaptor* buffer, std::size_t pos) {
|
||||
return buffer->at_pos(pos);
|
||||
}
|
||||
|
||||
static void push_back(fixed_size_buffer_adaptor* buffer, char ch) {
|
||||
buffer->push_back(ch);
|
||||
}
|
||||
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} // namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BUFFER_FIXED_HPP
|
78
include/protozero/buffer_string.hpp
Normal file
78
include/protozero/buffer_string.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef PROTOZERO_BUFFER_STRING_HPP
|
||||
#define PROTOZERO_BUFFER_STRING_HPP
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
protozero - Minimalistic protocol buffer decoder and encoder in C++.
|
||||
|
||||
This file is from https://github.com/mapbox/protozero where you can find more
|
||||
documentation.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file buffer_string.hpp
|
||||
*
|
||||
* @brief Contains the customization points for buffer implementation based
|
||||
* on std::string
|
||||
*/
|
||||
|
||||
#include "buffer_tmpl.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
// Implementation of buffer customizations points for std::string
|
||||
|
||||
/// @cond INTERNAL
|
||||
template <>
|
||||
struct buffer_customization<std::string> {
|
||||
|
||||
static std::size_t size(const std::string* buffer) noexcept {
|
||||
return buffer->size();
|
||||
}
|
||||
|
||||
static void append(std::string* buffer, const char* data, std::size_t count) {
|
||||
buffer->append(data, count);
|
||||
}
|
||||
|
||||
static void append_zeros(std::string* buffer, std::size_t count) {
|
||||
buffer->append(count, '\0');
|
||||
}
|
||||
|
||||
static void resize(std::string* buffer, std::size_t size) {
|
||||
protozero_assert(size < buffer->size());
|
||||
buffer->resize(size);
|
||||
}
|
||||
|
||||
static void reserve_additional(std::string* buffer, std::size_t size) {
|
||||
buffer->reserve(buffer->size() + size);
|
||||
}
|
||||
|
||||
static void erase_range(std::string* buffer, std::size_t from, std::size_t to) {
|
||||
protozero_assert(from <= buffer->size());
|
||||
protozero_assert(to <= buffer->size());
|
||||
protozero_assert(from <= to);
|
||||
buffer->erase(std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(from)),
|
||||
std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(to)));
|
||||
}
|
||||
|
||||
static char* at_pos(std::string* buffer, std::size_t pos) {
|
||||
protozero_assert(pos <= buffer->size());
|
||||
return (&*buffer->begin()) + pos;
|
||||
}
|
||||
|
||||
static void push_back(std::string* buffer, char ch) {
|
||||
buffer->push_back(ch);
|
||||
}
|
||||
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} // namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BUFFER_STRING_HPP
|
113
include/protozero/buffer_tmpl.hpp
Normal file
113
include/protozero/buffer_tmpl.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
#ifndef PROTOZERO_BUFFER_TMPL_HPP
|
||||
#define PROTOZERO_BUFFER_TMPL_HPP
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
protozero - Minimalistic protocol buffer decoder and encoder in C++.
|
||||
|
||||
This file is from https://github.com/mapbox/protozero where you can find more
|
||||
documentation.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file buffer_tmpl.hpp
|
||||
*
|
||||
* @brief Contains the customization points for buffer implementations.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
// Implementation of buffer customizations points for std::string
|
||||
|
||||
/// @cond INTERNAL
|
||||
template <typename T>
|
||||
struct buffer_customization {
|
||||
|
||||
/**
|
||||
* Get the number of bytes currently used in the buffer.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @returns number of bytes used in the buffer.
|
||||
*/
|
||||
static std::size_t size(const std::string* buffer);
|
||||
|
||||
/**
|
||||
* Append count bytes from data to the buffer.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param data Pointer to the data.
|
||||
* @param count Number of bytes to be added to the buffer.
|
||||
*/
|
||||
static void append(std::string* buffer, const char* data, std::size_t count);
|
||||
|
||||
/**
|
||||
* Append count zero bytes to the buffer.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param count Number of bytes to be added to the buffer.
|
||||
*/
|
||||
static void append_zeros(std::string* buffer, std::size_t count);
|
||||
|
||||
/**
|
||||
* Shrink the buffer to the specified size. The new size will always be
|
||||
* smaller than the current size.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param size New size of the buffer.
|
||||
*
|
||||
* @pre size < current size of buffer
|
||||
*/
|
||||
static void resize(std::string* buffer, std::size_t size);
|
||||
|
||||
/**
|
||||
* Reserve an additional size bytes for use in the buffer. This is used for
|
||||
* variable-sized buffers to tell the buffer implementation that soon more
|
||||
* memory will be used. The implementation can ignore this.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param size Number of bytes to reserve.
|
||||
*/
|
||||
static void reserve_additional(std::string* buffer, std::size_t size);
|
||||
|
||||
/**
|
||||
* Delete data from the buffer. This must move back the data after the
|
||||
* part being deleted and resize the buffer accordingly.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param from Offset into the buffer where we want to erase from.
|
||||
* @param to Offset into the buffer one past the last byte we want to erase.
|
||||
*
|
||||
* @pre from, to <= size of the buffer, from < to
|
||||
*/
|
||||
static void erase_range(std::string* buffer, std::size_t from, std::size_t to);
|
||||
|
||||
/**
|
||||
* Return a pointer to the memory at the specified position in the buffer.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param pos The position in the buffer.
|
||||
* @returns pointer to the memory in the buffer at the specified position.
|
||||
*
|
||||
* @pre pos <= size of the buffer
|
||||
*/
|
||||
static char* at_pos(std::string* buffer, std::size_t pos);
|
||||
|
||||
/**
|
||||
* Add a char to the buffer incrementing the number of chars in the buffer.
|
||||
*
|
||||
* @param buffer Pointer to the buffer.
|
||||
* @param ch The character to add.
|
||||
*/
|
||||
static void push_back(std::string* buffer, char ch);
|
||||
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} // namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BUFFER_TMPL_HPP
|
78
include/protozero/buffer_vector.hpp
Normal file
78
include/protozero/buffer_vector.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef PROTOZERO_BUFFER_VECTOR_HPP
|
||||
#define PROTOZERO_BUFFER_VECTOR_HPP
|
||||
|
||||
/*****************************************************************************
|
||||
|
||||
protozero - Minimalistic protocol buffer decoder and encoder in C++.
|
||||
|
||||
This file is from https://github.com/mapbox/protozero where you can find more
|
||||
documentation.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file buffer_vector.hpp
|
||||
*
|
||||
* @brief Contains the customization points for buffer implementation based
|
||||
* on std::vector<char>
|
||||
*/
|
||||
|
||||
#include "buffer_tmpl.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
// Implementation of buffer customizations points for std::vector<char>
|
||||
|
||||
/// @cond INTERNAL
|
||||
template <>
|
||||
struct buffer_customization<std::vector<char>> {
|
||||
|
||||
static std::size_t size(const std::vector<char>* buffer) noexcept {
|
||||
return buffer->size();
|
||||
}
|
||||
|
||||
static void append(std::vector<char>* buffer, const char* data, std::size_t count) {
|
||||
buffer->insert(buffer->end(), data, data + count);
|
||||
}
|
||||
|
||||
static void append_zeros(std::vector<char>* buffer, std::size_t count) {
|
||||
buffer->insert(buffer->end(), count, '\0');
|
||||
}
|
||||
|
||||
static void resize(std::vector<char>* buffer, std::size_t size) {
|
||||
protozero_assert(size < buffer->size());
|
||||
buffer->resize(size);
|
||||
}
|
||||
|
||||
static void reserve_additional(std::vector<char>* buffer, std::size_t size) {
|
||||
buffer->reserve(buffer->size() + size);
|
||||
}
|
||||
|
||||
static void erase_range(std::vector<char>* buffer, std::size_t from, std::size_t to) {
|
||||
protozero_assert(from <= buffer->size());
|
||||
protozero_assert(to <= buffer->size());
|
||||
protozero_assert(from <= to);
|
||||
buffer->erase(std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(from)),
|
||||
std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(to)));
|
||||
}
|
||||
|
||||
static char* at_pos(std::vector<char>* buffer, std::size_t pos) {
|
||||
protozero_assert(pos <= buffer->size());
|
||||
return (&*buffer->begin()) + pos;
|
||||
}
|
||||
|
||||
static void push_back(std::vector<char>* buffer, char ch) {
|
||||
buffer->push_back(ch);
|
||||
}
|
||||
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
} // namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BUFFER_VECTOR_HPP
|
@ -16,9 +16,10 @@ documentation.
|
||||
* @brief Contains functions to swap bytes in values (for different endianness).
|
||||
*/
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
#include "config.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace protozero {
|
||||
namespace detail {
|
||||
@ -27,10 +28,10 @@ inline uint32_t byteswap_impl(uint32_t value) noexcept {
|
||||
#ifdef PROTOZERO_USE_BUILTIN_BSWAP
|
||||
return __builtin_bswap32(value);
|
||||
#else
|
||||
return ((value & 0xff000000) >> 24) |
|
||||
((value & 0x00ff0000) >> 8) |
|
||||
((value & 0x0000ff00) << 8) |
|
||||
((value & 0x000000ff) << 24);
|
||||
return ((value & 0xff000000U) >> 24U) |
|
||||
((value & 0x00ff0000U) >> 8U) |
|
||||
((value & 0x0000ff00U) << 8U) |
|
||||
((value & 0x000000ffU) << 24U);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -38,46 +39,70 @@ inline uint64_t byteswap_impl(uint64_t value) noexcept {
|
||||
#ifdef PROTOZERO_USE_BUILTIN_BSWAP
|
||||
return __builtin_bswap64(value);
|
||||
#else
|
||||
return ((value & 0xff00000000000000ULL) >> 56) |
|
||||
((value & 0x00ff000000000000ULL) >> 40) |
|
||||
((value & 0x0000ff0000000000ULL) >> 24) |
|
||||
((value & 0x000000ff00000000ULL) >> 8) |
|
||||
((value & 0x00000000ff000000ULL) << 8) |
|
||||
((value & 0x0000000000ff0000ULL) << 24) |
|
||||
((value & 0x000000000000ff00ULL) << 40) |
|
||||
((value & 0x00000000000000ffULL) << 56);
|
||||
return ((value & 0xff00000000000000ULL) >> 56U) |
|
||||
((value & 0x00ff000000000000ULL) >> 40U) |
|
||||
((value & 0x0000ff0000000000ULL) >> 24U) |
|
||||
((value & 0x000000ff00000000ULL) >> 8U) |
|
||||
((value & 0x00000000ff000000ULL) << 8U) |
|
||||
((value & 0x0000000000ff0000ULL) << 24U) |
|
||||
((value & 0x000000000000ff00ULL) << 40U) |
|
||||
((value & 0x00000000000000ffULL) << 56U);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(uint32_t* ptr) noexcept {
|
||||
*ptr = byteswap_impl(*ptr);
|
||||
*ptr = detail::byteswap_impl(*ptr);
|
||||
}
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(uint64_t* ptr) noexcept {
|
||||
*ptr = byteswap_impl(*ptr);
|
||||
*ptr = detail::byteswap_impl(*ptr);
|
||||
}
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(int32_t* ptr) noexcept {
|
||||
auto bptr = reinterpret_cast<uint32_t*>(ptr);
|
||||
*bptr = byteswap_impl(*bptr);
|
||||
auto* bptr = reinterpret_cast<uint32_t*>(ptr);
|
||||
*bptr = detail::byteswap_impl(*bptr);
|
||||
}
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(int64_t* ptr) noexcept {
|
||||
auto bptr = reinterpret_cast<uint64_t*>(ptr);
|
||||
*bptr = byteswap_impl(*bptr);
|
||||
auto* bptr = reinterpret_cast<uint64_t*>(ptr);
|
||||
*bptr = detail::byteswap_impl(*bptr);
|
||||
}
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(float* ptr) noexcept {
|
||||
auto bptr = reinterpret_cast<uint32_t*>(ptr);
|
||||
*bptr = byteswap_impl(*bptr);
|
||||
static_assert(sizeof(float) == 4, "Expecting four byte float");
|
||||
|
||||
uint32_t tmp = 0;
|
||||
std::memcpy(&tmp, ptr, 4);
|
||||
tmp = detail::byteswap_impl(tmp); // uint32 overload
|
||||
std::memcpy(ptr, &tmp, 4);
|
||||
}
|
||||
|
||||
/// byteswap the data pointed to by ptr in-place.
|
||||
inline void byteswap_inplace(double* ptr) noexcept {
|
||||
auto bptr = reinterpret_cast<uint64_t*>(ptr);
|
||||
*bptr = byteswap_impl(*bptr);
|
||||
static_assert(sizeof(double) == 8, "Expecting eight byte double");
|
||||
|
||||
uint64_t tmp = 0;
|
||||
std::memcpy(&tmp, ptr, 8);
|
||||
tmp = detail::byteswap_impl(tmp); // uint64 overload
|
||||
std::memcpy(ptr, &tmp, 8);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Added for backwards compatibility with any code that might use this
|
||||
// function (even if it shouldn't have). Will be removed in a later
|
||||
// version of protozero.
|
||||
using ::protozero::byteswap_inplace;
|
||||
|
||||
} // end namespace detail
|
||||
|
||||
} // end namespace protozero
|
||||
|
||||
#endif // PROTOZERO_BYTESWAP_HPP
|
||||
|
@ -16,7 +16,7 @@ documentation.
|
||||
* @brief Contains the implementation of the data_view class.
|
||||
*/
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
#include "config.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@ -55,8 +55,8 @@ public:
|
||||
* @param length Length of the data.
|
||||
*/
|
||||
constexpr data_view(const char* ptr, std::size_t length) noexcept
|
||||
: m_data(ptr),
|
||||
m_size(length) {
|
||||
: m_data{ptr},
|
||||
m_size{length} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,8 +65,8 @@ public:
|
||||
* @param str String with the data.
|
||||
*/
|
||||
data_view(const std::string& str) noexcept // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
|
||||
: m_data(str.data()),
|
||||
m_size(str.size()) {
|
||||
: m_data{str.data()},
|
||||
m_size{str.size()} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,8 +75,8 @@ public:
|
||||
* @param ptr Pointer to the data.
|
||||
*/
|
||||
data_view(const char* ptr) noexcept // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
|
||||
: m_data(ptr),
|
||||
m_size(std::strlen(ptr)) {
|
||||
: m_data{ptr},
|
||||
m_size{std::strlen(ptr)} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,8 +141,8 @@ public:
|
||||
*
|
||||
* @pre Must not be default constructed data_view.
|
||||
*/
|
||||
int compare(data_view other) const {
|
||||
protozero_assert(m_data && other.m_data);
|
||||
int compare(data_view other) const noexcept {
|
||||
assert(m_data && other.m_data);
|
||||
const int cmp = std::memcmp(data(), other.data(),
|
||||
std::min(size(), other.size()));
|
||||
if (cmp == 0) {
|
||||
|
@ -16,8 +16,8 @@ documentation.
|
||||
* @brief Contains the iterators for access to packed repeated fields.
|
||||
*/
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
#include <protozero/varint.hpp>
|
||||
#include "config.hpp"
|
||||
#include "varint.hpp"
|
||||
|
||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
|
||||
# include <protozero/byteswap.hpp>
|
||||
@ -56,7 +56,7 @@ public:
|
||||
* Default constructor. Create empty iterator_range.
|
||||
*/
|
||||
constexpr iterator_range() :
|
||||
P(iterator{}, iterator{}) {
|
||||
P{iterator{}, iterator{}} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,8 +66,8 @@ public:
|
||||
* @param last_iterator Iterator to end of range.
|
||||
*/
|
||||
constexpr iterator_range(iterator&& first_iterator, iterator&& last_iterator) :
|
||||
P(std::forward<iterator>(first_iterator),
|
||||
std::forward<iterator>(last_iterator)) {
|
||||
P{std::forward<iterator>(first_iterator),
|
||||
std::forward<iterator>(last_iterator)} {
|
||||
}
|
||||
|
||||
/// Return iterator to beginning of range.
|
||||
@ -164,6 +164,8 @@ class const_fixed_iterator {
|
||||
|
||||
public:
|
||||
|
||||
/// @cond usual iterator functions not documented
|
||||
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -173,7 +175,7 @@ public:
|
||||
const_fixed_iterator() noexcept = default;
|
||||
|
||||
explicit const_fixed_iterator(const char* data) noexcept :
|
||||
m_data(data) {
|
||||
m_data{data} {
|
||||
}
|
||||
|
||||
const_fixed_iterator(const const_fixed_iterator&) noexcept = default;
|
||||
@ -184,11 +186,11 @@ public:
|
||||
|
||||
~const_fixed_iterator() noexcept = default;
|
||||
|
||||
value_type operator*() const {
|
||||
value_type operator*() const noexcept {
|
||||
value_type result;
|
||||
std::memcpy(&result, m_data, sizeof(value_type));
|
||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
|
||||
detail::byteswap_inplace(&result);
|
||||
byteswap_inplace(&result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@ -204,14 +206,6 @@ public:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator==(const_fixed_iterator rhs) const noexcept {
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
bool operator!=(const_fixed_iterator rhs) const noexcept {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
const_fixed_iterator& operator--() noexcept {
|
||||
m_data -= sizeof(value_type);
|
||||
return *this;
|
||||
@ -223,6 +217,14 @@ public:
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
|
||||
return lhs.m_data == rhs.m_data;
|
||||
}
|
||||
|
||||
friend bool operator!=(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
friend bool operator<(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
|
||||
return lhs.m_data < rhs.m_data;
|
||||
}
|
||||
@ -237,7 +239,6 @@ public:
|
||||
|
||||
friend bool operator>=(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
|
||||
return !(lhs < rhs);
|
||||
|
||||
}
|
||||
|
||||
const_fixed_iterator& operator+=(difference_type val) noexcept {
|
||||
@ -276,6 +277,8 @@ public:
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
}; // class const_fixed_iterator
|
||||
|
||||
/**
|
||||
@ -288,13 +291,15 @@ class const_varint_iterator {
|
||||
protected:
|
||||
|
||||
/// Pointer to current iterator position
|
||||
const char* m_data = nullptr;
|
||||
const char* m_data = nullptr; // NOLINT(misc-non-private-member-variables-in-classes, cppcoreguidelines-non-private-member-variables-in-classes,-warnings-as-errors)
|
||||
|
||||
/// Pointer to end iterator position
|
||||
const char* m_end = nullptr;
|
||||
const char* m_end = nullptr; // NOLINT(misc-non-private-member-variables-in-classes, cppcoreguidelines-non-private-member-variables-in-classes,-warnings-as-errors)
|
||||
|
||||
public:
|
||||
|
||||
/// @cond usual iterator functions not documented
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -302,19 +307,24 @@ public:
|
||||
using reference = value_type&;
|
||||
|
||||
static difference_type distance(const_varint_iterator begin, const_varint_iterator end) noexcept {
|
||||
// The "distance" between default initialized const_varint_iterator's
|
||||
// is always 0.
|
||||
if (!begin.m_data) {
|
||||
return 0;
|
||||
}
|
||||
// We know that each varint contains exactly one byte with the most
|
||||
// significant bit not set. We can use this to quickly figure out
|
||||
// how many varints there are without actually decoding the varints.
|
||||
return std::count_if(begin.m_data, end.m_data, [](char c) noexcept {
|
||||
return (static_cast<unsigned char>(c) & 0x80u) == 0;
|
||||
return (static_cast<unsigned char>(c) & 0x80U) == 0;
|
||||
});
|
||||
}
|
||||
|
||||
const_varint_iterator() noexcept = default;
|
||||
|
||||
const_varint_iterator(const char* data, const char* end) noexcept :
|
||||
m_data(data),
|
||||
m_end(end) {
|
||||
m_data{data},
|
||||
m_end{end} {
|
||||
}
|
||||
|
||||
const_varint_iterator(const const_varint_iterator&) noexcept = default;
|
||||
@ -326,16 +336,19 @@ public:
|
||||
~const_varint_iterator() noexcept = default;
|
||||
|
||||
value_type operator*() const {
|
||||
protozero_assert(m_data);
|
||||
const char* d = m_data; // will be thrown away
|
||||
return static_cast<value_type>(decode_varint(&d, m_end));
|
||||
}
|
||||
|
||||
const_varint_iterator& operator++() {
|
||||
protozero_assert(m_data);
|
||||
skip_varint(&m_data, m_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_varint_iterator operator++(int) {
|
||||
protozero_assert(m_data);
|
||||
const const_varint_iterator tmp{*this};
|
||||
++(*this);
|
||||
return tmp;
|
||||
@ -349,6 +362,8 @@ public:
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
}; // class const_varint_iterator
|
||||
|
||||
/**
|
||||
@ -360,6 +375,8 @@ class const_svarint_iterator : public const_varint_iterator<T> {
|
||||
|
||||
public:
|
||||
|
||||
/// @cond usual iterator functions not documented
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
@ -367,11 +384,11 @@ public:
|
||||
using reference = value_type&;
|
||||
|
||||
const_svarint_iterator() noexcept :
|
||||
const_varint_iterator<T>() {
|
||||
const_varint_iterator<T>{} {
|
||||
}
|
||||
|
||||
const_svarint_iterator(const char* data, const char* end) noexcept :
|
||||
const_varint_iterator<T>(data, end) {
|
||||
const_varint_iterator<T>{data, end} {
|
||||
}
|
||||
|
||||
const_svarint_iterator(const const_svarint_iterator&) = default;
|
||||
@ -383,21 +400,26 @@ public:
|
||||
~const_svarint_iterator() = default;
|
||||
|
||||
value_type operator*() const {
|
||||
protozero_assert(this->m_data);
|
||||
const char* d = this->m_data; // will be thrown away
|
||||
return static_cast<value_type>(decode_zigzag64(decode_varint(&d, this->m_end)));
|
||||
}
|
||||
|
||||
const_svarint_iterator& operator++() {
|
||||
protozero_assert(this->m_data);
|
||||
skip_varint(&this->m_data, this->m_end);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_svarint_iterator operator++(int) {
|
||||
protozero_assert(this->m_data);
|
||||
const const_svarint_iterator tmp{*this};
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
}; // class const_svarint_iterator
|
||||
|
||||
} // end namespace protozero
|
||||
@ -408,6 +430,8 @@ namespace std {
|
||||
// functions can't be partially specialized, we have to do this for
|
||||
// every value_type we are using.
|
||||
|
||||
/// @cond individual overloads do not need to be documented
|
||||
|
||||
template <>
|
||||
inline typename protozero::const_varint_iterator<int32_t>::difference_type
|
||||
distance<protozero::const_varint_iterator<int32_t>>(protozero::const_varint_iterator<int32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
|
||||
@ -450,6 +474,8 @@ namespace std {
|
||||
return protozero::const_svarint_iterator<int64_t>::distance(first, last);
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
} // end namespace std
|
||||
|
||||
#endif // PROTOZERO_ITERATORS_HPP
|
||||
|
@ -16,249 +16,16 @@ documentation.
|
||||
* @brief Contains the pbf_builder template class.
|
||||
*/
|
||||
|
||||
#include <protozero/pbf_writer.hpp>
|
||||
#include <protozero/types.hpp>
|
||||
#include "basic_pbf_builder.hpp"
|
||||
#include "pbf_writer.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
|
||||
namespace protozero {
|
||||
|
||||
/**
|
||||
* The pbf_builder is used to write PBF formatted messages into a buffer. It
|
||||
* is based on the pbf_writer class and has all the same methods. The
|
||||
* difference is that while the pbf_writer class takes an integer tag,
|
||||
* this template class takes a tag of the template type T. The idea is that
|
||||
* T will be an enumeration value and this helps reduce the possibility of
|
||||
* programming errors.
|
||||
*
|
||||
* Almost all methods in this class can throw an std::bad_alloc exception if
|
||||
* the std::string used as a buffer wants to resize.
|
||||
*
|
||||
* Read the tutorial to understand how this class is used.
|
||||
*/
|
||||
/// Specialization of basic_pbf_builder using std::string as buffer type.
|
||||
template <typename T>
|
||||
class pbf_builder : public pbf_writer {
|
||||
|
||||
static_assert(std::is_same<pbf_tag_type, typename std::underlying_type<T>::type>::value,
|
||||
"T must be enum with underlying type protozero::pbf_tag_type");
|
||||
|
||||
public:
|
||||
|
||||
/// The type of messages this class will build.
|
||||
using enum_type = T;
|
||||
|
||||
pbf_builder() = default;
|
||||
|
||||
/**
|
||||
* Create a builder using the given string as a data store. The object
|
||||
* stores a reference to that string and adds all data to it. The string
|
||||
* doesn't have to be empty. The pbf_message object will just append data.
|
||||
*/
|
||||
explicit pbf_builder(std::string& data) noexcept :
|
||||
pbf_writer(data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a pbf_builder for a submessage from the pbf_message or
|
||||
* pbf_writer of the parent message.
|
||||
*
|
||||
* @param parent_writer The parent pbf_message or pbf_writer
|
||||
* @param tag Tag of the field that will be written
|
||||
*/
|
||||
template <typename P>
|
||||
pbf_builder(pbf_writer& parent_writer, P tag) noexcept :
|
||||
pbf_writer(parent_writer, pbf_tag_type(tag)) {
|
||||
}
|
||||
|
||||
/// @cond INTERNAL
|
||||
#define PROTOZERO_WRITER_WRAP_ADD_SCALAR(name, type) \
|
||||
void add_##name(T tag, type value) { \
|
||||
pbf_writer::add_##name(pbf_tag_type(tag), value); \
|
||||
}
|
||||
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(bool, bool)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(enum, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(int32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sint32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(uint32, uint32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(int64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sint64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(uint64, uint64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(fixed32, uint32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sfixed32, int32_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(fixed64, uint64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(sfixed64, int64_t)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(float, float)
|
||||
PROTOZERO_WRITER_WRAP_ADD_SCALAR(double, double)
|
||||
|
||||
#undef PROTOZERO_WRITER_WRAP_ADD_SCALAR
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
* @param size Number of bytes to be written
|
||||
*/
|
||||
void add_bytes(T tag, const char* value, std::size_t size) {
|
||||
pbf_writer::add_bytes(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const data_view& value) {
|
||||
pbf_writer::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const std::string& value) {
|
||||
pbf_writer::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data. Bytes from the value are written until
|
||||
* a null byte is encountered. The null byte is not added.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to zero-delimited value to be written
|
||||
*/
|
||||
void add_bytes(T tag, const char* value) {
|
||||
pbf_writer::add_bytes(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "bytes" field to data using vectored input. All the data in the
|
||||
* 2nd and further arguments is "concatenated" with only a single copy
|
||||
* into the final buffer.
|
||||
*
|
||||
* This will work with objects of any type supporting the data() and
|
||||
* size() methods like std::string or protozero::data_view.
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* std::string data1 = "abc";
|
||||
* std::string data2 = "xyz";
|
||||
* builder.add_bytes_vectored(1, data1, data2);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam Ts List of types supporting data() and size() methods.
|
||||
* @param tag Tag of the field
|
||||
* @param values List of objects of types Ts with data to be appended.
|
||||
*/
|
||||
template <typename... Ts>
|
||||
void add_bytes_vectored(T tag, Ts&&... values) {
|
||||
pbf_writer::add_bytes_vectored(pbf_tag_type(tag), std::forward<Ts>(values)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
* @param size Number of bytes to be written
|
||||
*/
|
||||
void add_string(T tag, const char* value, std::size_t size) {
|
||||
pbf_writer::add_string(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_string(T tag, const data_view& value) {
|
||||
pbf_writer::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written
|
||||
*/
|
||||
void add_string(T tag, const std::string& value) {
|
||||
pbf_writer::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "string" field to data. Bytes from the value are written until
|
||||
* a null byte is encountered. The null byte is not added.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to value to be written
|
||||
*/
|
||||
void add_string(T tag, const char* value) {
|
||||
pbf_writer::add_string(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Pointer to message to be written
|
||||
* @param size Length of the message
|
||||
*/
|
||||
void add_message(T tag, const char* value, std::size_t size) {
|
||||
pbf_writer::add_message(pbf_tag_type(tag), value, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written. The value must be a complete message.
|
||||
*/
|
||||
void add_message(T tag, const data_view& value) {
|
||||
pbf_writer::add_message(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "message" field to data.
|
||||
*
|
||||
* @param tag Tag of the field
|
||||
* @param value Value to be written. The value must be a complete message.
|
||||
*/
|
||||
void add_message(T tag, const std::string& value) {
|
||||
pbf_writer::add_message(pbf_tag_type(tag), value);
|
||||
}
|
||||
|
||||
/// @cond INTERNAL
|
||||
#define PROTOZERO_WRITER_WRAP_ADD_PACKED(name) \
|
||||
template <typename InputIterator> \
|
||||
void add_packed_##name(T tag, InputIterator first, InputIterator last) { \
|
||||
pbf_writer::add_packed_##name(pbf_tag_type(tag), first, last); \
|
||||
}
|
||||
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(bool)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(enum)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(int32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sint32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(uint32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(int64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sint64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(uint64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(fixed32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sfixed32)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(fixed64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(sfixed64)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(float)
|
||||
PROTOZERO_WRITER_WRAP_ADD_PACKED(double)
|
||||
|
||||
#undef PROTOZERO_WRITER_WRAP_ADD_PACKED
|
||||
/// @endcond
|
||||
|
||||
}; // class pbf_builder
|
||||
using pbf_builder = basic_pbf_builder<std::string, T>;
|
||||
|
||||
} // end namespace protozero
|
||||
|
||||
|
@ -16,8 +16,8 @@ documentation.
|
||||
* @brief Contains the pbf_message template class.
|
||||
*/
|
||||
|
||||
#include <protozero/pbf_reader.hpp>
|
||||
#include <protozero/types.hpp>
|
||||
#include "pbf_reader.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@ -78,7 +78,7 @@ public:
|
||||
*/
|
||||
template <typename... Args>
|
||||
pbf_message(Args&&... args) noexcept : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
|
||||
pbf_reader(std::forward<Args>(args)...) {
|
||||
pbf_reader{std::forward<Args>(args)...} {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,12 +16,12 @@ documentation.
|
||||
* @brief Contains the pbf_reader class.
|
||||
*/
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
#include <protozero/data_view.hpp>
|
||||
#include <protozero/exception.hpp>
|
||||
#include <protozero/iterators.hpp>
|
||||
#include <protozero/types.hpp>
|
||||
#include <protozero/varint.hpp>
|
||||
#include "config.hpp"
|
||||
#include "data_view.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "iterators.hpp"
|
||||
#include "types.hpp"
|
||||
#include "varint.hpp"
|
||||
|
||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
|
||||
# include <protozero/byteswap.hpp>
|
||||
@ -80,7 +80,7 @@ class pbf_reader {
|
||||
skip_bytes(sizeof(T));
|
||||
std::memcpy(&result, data, sizeof(T));
|
||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
|
||||
detail::byteswap_inplace(&result);
|
||||
byteswap_inplace(&result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@ -98,7 +98,8 @@ class pbf_reader {
|
||||
|
||||
template <typename T>
|
||||
T get_varint() {
|
||||
return static_cast<T>(decode_varint(&m_data, m_end));
|
||||
const auto val = static_cast<T>(decode_varint(&m_data, m_end));
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -112,7 +113,7 @@ class pbf_reader {
|
||||
}
|
||||
|
||||
void skip_bytes(pbf_length_type len) {
|
||||
if (m_data + len > m_end) {
|
||||
if (m_end - m_data < static_cast<ptrdiff_t>(len)) {
|
||||
throw end_of_buffer_exception{};
|
||||
}
|
||||
m_data += len;
|
||||
@ -151,8 +152,8 @@ public:
|
||||
* @post There is no current field.
|
||||
*/
|
||||
explicit pbf_reader(const data_view& view) noexcept
|
||||
: m_data(view.data()),
|
||||
m_end(view.data() + view.size()) {
|
||||
: m_data{view.data()},
|
||||
m_end{view.data() + view.size()} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,8 +167,8 @@ public:
|
||||
* @post There is no current field.
|
||||
*/
|
||||
pbf_reader(const char* data, std::size_t size) noexcept
|
||||
: m_data(data),
|
||||
m_end(data + size) {
|
||||
: m_data{data},
|
||||
m_end{data + size} {
|
||||
}
|
||||
|
||||
#ifndef PROTOZERO_STRICT_API
|
||||
@ -183,8 +184,8 @@ public:
|
||||
* @deprecated Use one of the other constructors.
|
||||
*/
|
||||
explicit pbf_reader(const std::pair<const char*, std::size_t>& data) noexcept
|
||||
: m_data(data.first),
|
||||
m_end(data.first + data.second) {
|
||||
: m_data{data.first},
|
||||
m_end{data.first + data.second} {
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -199,8 +200,8 @@ public:
|
||||
* @post There is no current field.
|
||||
*/
|
||||
explicit pbf_reader(const std::string& data) noexcept
|
||||
: m_data(data.data()),
|
||||
m_end(data.data() + data.size()) {
|
||||
: m_data{data.data()},
|
||||
m_end{data.data() + data.size()} {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,7 +243,14 @@ public:
|
||||
* read.
|
||||
*/
|
||||
operator bool() const noexcept { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
|
||||
return m_data < m_end;
|
||||
return m_data != m_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a view of the not yet read data.
|
||||
*/
|
||||
data_view data() const noexcept {
|
||||
return {m_data, static_cast<std::size_t>(m_end - m_data)};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,7 +287,7 @@ public:
|
||||
}
|
||||
|
||||
const auto value = get_varint<uint32_t>();
|
||||
m_tag = pbf_tag_type(value >> 3u);
|
||||
m_tag = pbf_tag_type(value >> 3U);
|
||||
|
||||
// tags 0 and 19000 to 19999 are not allowed as per
|
||||
// https://developers.google.com/protocol-buffers/docs/proto#assigning-tags
|
||||
@ -287,7 +295,7 @@ public:
|
||||
throw invalid_tag_exception{};
|
||||
}
|
||||
|
||||
m_wire_type = pbf_wire_type(value & 0x07u);
|
||||
m_wire_type = pbf_wire_type(value & 0x07U);
|
||||
switch (m_wire_type) {
|
||||
case pbf_wire_type::varint:
|
||||
case pbf_wire_type::fixed64:
|
||||
@ -486,9 +494,9 @@ public:
|
||||
bool get_bool() {
|
||||
protozero_assert(tag() != 0 && "call next() before accessing field value");
|
||||
protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
|
||||
const auto data = m_data;
|
||||
const bool result = m_data[0] != 0;
|
||||
skip_varint(&m_data, m_end);
|
||||
return data[0] != 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@ documentation.
|
||||
* @brief Contains the declaration of low-level types used in the pbf format.
|
||||
*/
|
||||
|
||||
#include <protozero/config.hpp>
|
||||
#include "config.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
@ -53,7 +53,7 @@ enum class pbf_wire_type : uint32_t {
|
||||
*/
|
||||
template <typename T>
|
||||
constexpr inline uint32_t tag_and_type(T tag, pbf_wire_type wire_type) noexcept {
|
||||
return (static_cast<uint32_t>(static_cast<pbf_tag_type>(tag)) << 3u) | static_cast<uint32_t>(wire_type);
|
||||
return (static_cast<uint32_t>(static_cast<pbf_tag_type>(tag)) << 3U) | static_cast<uint32_t>(wire_type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,7 +16,8 @@ documentation.
|
||||
* @brief Contains low-level varint and zigzag encoding and decoding functions.
|
||||
*/
|
||||
|
||||
#include <protozero/exception.hpp>
|
||||
#include "buffer_tmpl.hpp"
|
||||
#include "exception.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@ -31,30 +32,30 @@ namespace detail {
|
||||
|
||||
// from https://github.com/facebook/folly/blob/master/folly/Varint.h
|
||||
inline uint64_t decode_varint_impl(const char** data, const char* end) {
|
||||
const auto begin = reinterpret_cast<const int8_t*>(*data);
|
||||
const auto iend = reinterpret_cast<const int8_t*>(end);
|
||||
const auto* begin = reinterpret_cast<const int8_t*>(*data);
|
||||
const auto* iend = reinterpret_cast<const int8_t*>(end);
|
||||
const int8_t* p = begin;
|
||||
uint64_t val = 0;
|
||||
|
||||
if (iend - begin >= max_varint_length) { // fast path
|
||||
do {
|
||||
int64_t b;
|
||||
b = *p++; val = uint64_t((b & 0x7fu) ); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 7u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 14u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 21u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 28u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 35u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 42u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 49u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x7fu) << 56u); if (b >= 0) { break; }
|
||||
b = *p++; val |= uint64_t((b & 0x01u) << 63u); if (b >= 0) { break; }
|
||||
int64_t b = *p++;
|
||||
val = ((uint64_t(b) & 0x7fU) ); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 7U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 14U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 21U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 28U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 35U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 42U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 49U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x7fU) << 56U); if (b >= 0) { break; }
|
||||
b = *p++; val |= ((uint64_t(b) & 0x01U) << 63U); if (b >= 0) { break; }
|
||||
throw varint_too_long_exception{};
|
||||
} while (false);
|
||||
} else {
|
||||
unsigned int shift = 0;
|
||||
while (p != iend && *p < 0) {
|
||||
val |= uint64_t(*p++ & 0x7fu) << shift;
|
||||
val |= (uint64_t(*p++) & 0x7fU) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
if (p == iend) {
|
||||
@ -88,7 +89,7 @@ namespace detail {
|
||||
*/
|
||||
inline uint64_t decode_varint(const char** data, const char* end) {
|
||||
// If this is a one-byte varint, decode it here.
|
||||
if (end != *data && ((**data & 0x80u) == 0)) {
|
||||
if (end != *data && ((static_cast<uint64_t>(**data) & 0x80U) == 0)) {
|
||||
const auto val = static_cast<uint64_t>(**data);
|
||||
++(*data);
|
||||
return val;
|
||||
@ -110,15 +111,15 @@ inline uint64_t decode_varint(const char** data, const char* end) {
|
||||
* before the end of the varint.
|
||||
*/
|
||||
inline void skip_varint(const char** data, const char* end) {
|
||||
const auto begin = reinterpret_cast<const int8_t*>(*data);
|
||||
const auto iend = reinterpret_cast<const int8_t*>(end);
|
||||
const auto* begin = reinterpret_cast<const int8_t*>(*data);
|
||||
const auto* iend = reinterpret_cast<const int8_t*>(end);
|
||||
const int8_t* p = begin;
|
||||
|
||||
while (p != iend && *p < 0) {
|
||||
++p;
|
||||
}
|
||||
|
||||
if (p >= begin + max_varint_length) {
|
||||
if (p - begin >= max_varint_length) {
|
||||
throw varint_too_long_exception{};
|
||||
}
|
||||
|
||||
@ -140,17 +141,73 @@ inline void skip_varint(const char** data, const char* end) {
|
||||
* @param value The integer that will be encoded.
|
||||
* @returns the number of bytes written
|
||||
* @throws Any exception thrown by increment or dereference operator on data.
|
||||
* @deprecated Use add_varint_to_buffer() instead.
|
||||
*/
|
||||
template <typename T>
|
||||
inline int write_varint(T data, uint64_t value) {
|
||||
int n = 1;
|
||||
|
||||
while (value >= 0x80u) {
|
||||
*data++ = char((value & 0x7fu) | 0x80u);
|
||||
value >>= 7u;
|
||||
while (value >= 0x80U) {
|
||||
*data++ = char((value & 0x7fU) | 0x80U);
|
||||
value >>= 7U;
|
||||
++n;
|
||||
}
|
||||
*data = char(value);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Varint encode a 64 bit integer.
|
||||
*
|
||||
* @tparam TBuffer A buffer type.
|
||||
* @param buffer Output buffer the varint will be written to.
|
||||
* @param value The integer that will be encoded.
|
||||
* @returns the number of bytes written
|
||||
* @throws Any exception thrown by calling the buffer_push_back() function.
|
||||
*/
|
||||
template <typename TBuffer>
|
||||
inline void add_varint_to_buffer(TBuffer* buffer, uint64_t value) {
|
||||
while (value >= 0x80U) {
|
||||
buffer_customization<TBuffer>::push_back(buffer, char((value & 0x7fU) | 0x80U));
|
||||
value >>= 7U;
|
||||
}
|
||||
buffer_customization<TBuffer>::push_back(buffer, char(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Varint encode a 64 bit integer.
|
||||
*
|
||||
* @param data Where to add the varint. There must be enough space available!
|
||||
* @param value The integer that will be encoded.
|
||||
* @returns the number of bytes written
|
||||
*/
|
||||
inline int add_varint_to_buffer(char* data, uint64_t value) noexcept {
|
||||
int n = 1;
|
||||
|
||||
while (value >= 0x80U) {
|
||||
*data++ = char((value & 0x7fU) | 0x80U);
|
||||
value >>= 7U;
|
||||
++n;
|
||||
}
|
||||
*data = char(value);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of the varint the specified value would produce.
|
||||
*
|
||||
* @param value The integer to be encoded.
|
||||
* @returns the number of bytes the varint would have if we created it.
|
||||
*/
|
||||
inline int length_of_varint(uint64_t value) noexcept {
|
||||
int n = 1;
|
||||
|
||||
while (value >= 0x80U) {
|
||||
value >>= 7U;
|
||||
++n;
|
||||
}
|
||||
*data++ = char(value);
|
||||
|
||||
return n;
|
||||
}
|
||||
@ -159,28 +216,28 @@ inline int write_varint(T data, uint64_t value) {
|
||||
* ZigZag encodes a 32 bit integer.
|
||||
*/
|
||||
inline constexpr uint32_t encode_zigzag32(int32_t value) noexcept {
|
||||
return (static_cast<uint32_t>(value) << 1u) ^ (static_cast<uint32_t>(value >> 31u));
|
||||
return (static_cast<uint32_t>(value) << 1U) ^ static_cast<uint32_t>(-static_cast<int32_t>(static_cast<uint32_t>(value) >> 31U));
|
||||
}
|
||||
|
||||
/**
|
||||
* ZigZag encodes a 64 bit integer.
|
||||
*/
|
||||
inline constexpr uint64_t encode_zigzag64(int64_t value) noexcept {
|
||||
return (static_cast<uint64_t>(value) << 1u) ^ (static_cast<uint64_t>(value >> 63u));
|
||||
return (static_cast<uint64_t>(value) << 1U) ^ static_cast<uint64_t>(-static_cast<int64_t>(static_cast<uint64_t>(value) >> 63U));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a 32 bit ZigZag-encoded integer.
|
||||
*/
|
||||
inline constexpr int32_t decode_zigzag32(uint32_t value) noexcept {
|
||||
return static_cast<int32_t>(value >> 1u) ^ -static_cast<int32_t>(value & 1u);
|
||||
return static_cast<int32_t>((value >> 1U) ^ static_cast<uint32_t>(-static_cast<int32_t>(value & 1U)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a 64 bit ZigZag-encoded integer.
|
||||
*/
|
||||
inline constexpr int64_t decode_zigzag64(uint64_t value) noexcept {
|
||||
return static_cast<int64_t>(value >> 1u) ^ -static_cast<int64_t>(value & 1u);
|
||||
return static_cast<int64_t>((value >> 1U) ^ static_cast<uint64_t>(-static_cast<int64_t>(value & 1U)));
|
||||
}
|
||||
|
||||
} // end namespace protozero
|
||||
|
@ -20,15 +20,15 @@ documentation.
|
||||
#define PROTOZERO_VERSION_MAJOR 1
|
||||
|
||||
/// The minor version number
|
||||
#define PROTOZERO_VERSION_MINOR 6
|
||||
#define PROTOZERO_VERSION_MINOR 7
|
||||
|
||||
/// The patch number
|
||||
#define PROTOZERO_VERSION_PATCH 2
|
||||
#define PROTOZERO_VERSION_PATCH 1
|
||||
|
||||
/// The complete version number
|
||||
#define PROTOZERO_VERSION_CODE (PROTOZERO_VERSION_MAJOR * 10000 + PROTOZERO_VERSION_MINOR * 100 + PROTOZERO_VERSION_PATCH)
|
||||
|
||||
/// Version number as string
|
||||
#define PROTOZERO_VERSION_STRING "1.6.2"
|
||||
#define PROTOZERO_VERSION_STRING "1.7.1"
|
||||
|
||||
#endif // PROTOZERO_VERSION_HPP
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
# Tests
|
||||
|
||||
Tests are using the [Catch Unit Test Framework](https://github.com/philsquared/Catch).
|
||||
Tests are using the [Catch Unit Test Framework](https://github.com/catchorg/Catch2).
|
||||
|
||||
## Organization of the unit tests
|
||||
|
||||
|
25150
test/catch/catch.hpp
25150
test/catch/catch.hpp
File diff suppressed because it is too large
Load Diff
@ -8,9 +8,16 @@
|
||||
# If called without a test case it will iterate over all test cases generating
|
||||
# all data.
|
||||
#
|
||||
# This program should be called with the "test" directory as current directory.
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$CXX" ]; then
|
||||
echo "Please set CXX before running this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
for dir in t/*; do
|
||||
$0 $dir
|
||||
|
163
test/include/buffer.hpp
Normal file
163
test/include/buffer.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef BUFFER_HPP
|
||||
#define BUFFER_HPP
|
||||
|
||||
#include "test.hpp"
|
||||
|
||||
#include <protozero/buffer_fixed.hpp>
|
||||
#include <protozero/buffer_string.hpp>
|
||||
#include <protozero/buffer_vector.hpp>
|
||||
|
||||
// This "simulates" an externally defined buffer type to make sure our
|
||||
// buffer adaptor functions do the right thing.
|
||||
namespace test_external {
|
||||
class ext_buffer : public std::string {
|
||||
};
|
||||
} // namespace test_external
|
||||
|
||||
namespace protozero {
|
||||
|
||||
template <>
|
||||
struct buffer_customization<test_external::ext_buffer> {
|
||||
|
||||
static std::size_t size(const test_external::ext_buffer* buffer) noexcept {
|
||||
return buffer->size();
|
||||
}
|
||||
|
||||
static void append(test_external::ext_buffer* buffer, const char* data, std::size_t count) {
|
||||
buffer->append(data, count);
|
||||
}
|
||||
|
||||
static void append_zeros(test_external::ext_buffer* buffer, std::size_t count) {
|
||||
buffer->append(count, '\0');
|
||||
}
|
||||
|
||||
static void resize(test_external::ext_buffer* buffer, std::size_t size) {
|
||||
protozero_assert(size < buffer->size());
|
||||
buffer->resize(size);
|
||||
}
|
||||
|
||||
static void reserve_additional(test_external::ext_buffer* buffer, std::size_t size) {
|
||||
buffer->reserve(buffer->size() + size);
|
||||
}
|
||||
|
||||
static void erase_range(test_external::ext_buffer* buffer, std::size_t from, std::size_t to) {
|
||||
protozero_assert(from <= buffer->size());
|
||||
protozero_assert(to <= buffer->size());
|
||||
protozero_assert(from <= to);
|
||||
buffer->erase(std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(from)),
|
||||
std::next(buffer->begin(), static_cast<std::string::iterator::difference_type>(to)));
|
||||
}
|
||||
|
||||
static char* at_pos(test_external::ext_buffer* buffer, std::size_t pos) {
|
||||
protozero_assert(pos <= buffer->size());
|
||||
return (&*buffer->begin()) + pos;
|
||||
}
|
||||
|
||||
static void push_back(test_external::ext_buffer* buffer, char ch) {
|
||||
buffer->push_back(ch);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace protozero
|
||||
|
||||
// The following structs are used in many tests using TEMPLATE_TEST_CASE() to
|
||||
// test the different buffer types:
|
||||
//
|
||||
// 1. Dynamically sized buffer based on std::string.
|
||||
// 2. Dynamically sized buffer based on std::vector<char>.
|
||||
// 3. Statically sized buffer based on std::array<char, N>.
|
||||
// 4. Externally defined buffer.
|
||||
|
||||
class buffer_test_string {
|
||||
|
||||
std::string m_buffer;
|
||||
|
||||
public:
|
||||
|
||||
using type = std::string;
|
||||
using writer_type = protozero::pbf_writer; // == protozero::basic_pbf_writer<type>;
|
||||
|
||||
type& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const char *data() const noexcept {
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept {
|
||||
return m_buffer.size();
|
||||
}
|
||||
}; // class buffer_test_string
|
||||
|
||||
class buffer_test_vector {
|
||||
|
||||
std::vector<char> m_buffer;
|
||||
|
||||
public:
|
||||
|
||||
using type = std::vector<char>;
|
||||
using writer_type = protozero::basic_pbf_writer<type>;
|
||||
|
||||
type& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const char *data() const noexcept {
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept {
|
||||
return m_buffer.size();
|
||||
}
|
||||
}; // class buffer_test_vector
|
||||
|
||||
class buffer_test_array {
|
||||
|
||||
public:
|
||||
using type = protozero::fixed_size_buffer_adaptor;
|
||||
using writer_type = protozero::basic_pbf_writer<type>;
|
||||
|
||||
type& buffer() noexcept {
|
||||
return adaptor;
|
||||
}
|
||||
|
||||
const char *data() const noexcept {
|
||||
return adaptor.data();
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept {
|
||||
return adaptor.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::array<char, 1024> m_buffer = {{0}};
|
||||
type adaptor{m_buffer};
|
||||
|
||||
}; // class buffer_test_array
|
||||
|
||||
class buffer_test_external {
|
||||
|
||||
test_external::ext_buffer m_buffer;
|
||||
|
||||
public:
|
||||
|
||||
using type = test_external::ext_buffer;
|
||||
using writer_type = protozero::basic_pbf_writer<type>;
|
||||
|
||||
type& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
const char *data() const noexcept {
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept {
|
||||
return m_buffer.size();
|
||||
}
|
||||
}; // class buffer_test_external
|
||||
|
||||
#endif // BUFFER_HPP
|
@ -1,5 +1,8 @@
|
||||
// NOLINT(llvm-header-guard)
|
||||
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
|
||||
#define PBF_TYPE_NAME PROTOZERO_TEST_STRING(PBF_TYPE)
|
||||
#define GET_TYPE PROTOZERO_TEST_CONCAT(get_packed_, PBF_TYPE)
|
||||
#define ADD_TYPE PROTOZERO_TEST_CONCAT(add_packed_, PBF_TYPE)
|
||||
@ -92,7 +95,7 @@ TEST_CASE("read repeated packed field: " PBF_TYPE_NAME) {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.GET_TYPE(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.GET_TYPE(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,21 +108,27 @@ TEST_CASE("write repeated packed field: " PBF_TYPE_NAME) {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("empty") {
|
||||
cpp_type data[] = { 17 };
|
||||
std::array<cpp_type, 1> data = {{ 17 }};
|
||||
pw.ADD_TYPE(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-empty"));
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
cpp_type data[] = { 17 };
|
||||
std::array<cpp_type, 1> data = {{ 17 }};
|
||||
pw.ADD_TYPE(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-one"));
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
cpp_type data[] = {
|
||||
std::array<cpp_type,
|
||||
#if PBF_TYPE_IS_SIGNED
|
||||
8
|
||||
#else
|
||||
5
|
||||
#endif
|
||||
> data = {{
|
||||
17
|
||||
, 200
|
||||
, 0
|
||||
@ -130,7 +139,7 @@ TEST_CASE("write repeated packed field: " PBF_TYPE_NAME) {
|
||||
, -1
|
||||
,std::numeric_limits<cpp_type>::min()
|
||||
#endif
|
||||
};
|
||||
}};
|
||||
pw.ADD_TYPE(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-many"));
|
||||
@ -246,9 +255,9 @@ TEST_CASE("write from different types of iterators: " PBF_TYPE_NAME) {
|
||||
|
||||
SECTION("from uint16_t") {
|
||||
#if PBF_TYPE_IS_SIGNED
|
||||
const int16_t data[] = { 1, 4, 9, 16, 25 };
|
||||
const std::array< int16_t, 5> data = {{ 1, 4, 9, 16, 25 }};
|
||||
#else
|
||||
const uint16_t data[] = { 1, 4, 9, 16, 25 };
|
||||
const std::array<uint16_t, 5> data = {{ 1, 4, 9, 16, 25 }};
|
||||
#endif
|
||||
|
||||
pw.ADD_TYPE(1, std::begin(data), std::end(data));
|
||||
@ -290,7 +299,7 @@ TEST_CASE("write from different types of iterators: " PBF_TYPE_NAME) {
|
||||
REQUIRE(std::distance(it_range.begin(), it_range.end()) == 0);
|
||||
REQUIRE(it_range.size() == 0); // NOLINT(readability-container-size-empty)
|
||||
|
||||
REQUIRE_THROWS_AS(it_range.front(), const assert_error&);
|
||||
REQUIRE_THROWS_AS(it_range.drop_front(), const assert_error&);
|
||||
REQUIRE_THROWS_AS(it_range.front(), assert_error);
|
||||
REQUIRE_THROWS_AS(it_range.drop_front(), assert_error);
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ TEST_CASE("read field: " PBF_TYPE_NAME) {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.GET_TYPE(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.GET_TYPE(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include <stdexcept>
|
||||
// Define protozero_assert() to throw this error. This allows the tests to
|
||||
// check that the assert fails.
|
||||
|
@ -1,5 +1,7 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
@ -7,7 +9,7 @@
|
||||
#include <test.hpp> // IWYU pragma: keep
|
||||
|
||||
std::string load_data(const std::string& filename) {
|
||||
const char* tests_dir = std::getenv("TESTS_DIR");
|
||||
const char* tests_dir = std::getenv("TESTS_DIR"); // NOLINT(concurrency-mt-unsafe) okay in test
|
||||
if (tests_dir == nullptr) {
|
||||
tests_dir = "test";
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ TEST_CASE("check alignment issues for fixed32 field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_fixed32(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_fixed32(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ TEST_CASE("check alignment issues for fixed32 field") {
|
||||
abuffer.append(load_data("fixed32/data-zero"));
|
||||
protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
|
||||
|
||||
REQUIRE_THROWS_AS(item.get_fixed32(), const assert_error&);
|
||||
REQUIRE_THROWS_AS(item.get_fixed32(), assert_error);
|
||||
REQUIRE(item.next());
|
||||
REQUIRE(item.get_fixed32() == 0UL);
|
||||
REQUIRE_THROWS(item.get_fixed32());
|
||||
@ -66,7 +66,7 @@ TEST_CASE("check alignment issues for fixed32 field") {
|
||||
abuffer.append(load_data("fixed32/data-zero"));
|
||||
protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
|
||||
|
||||
REQUIRE_THROWS_AS(item.skip(), const assert_error&);
|
||||
REQUIRE_THROWS_AS(item.skip(), assert_error);
|
||||
REQUIRE(item.next());
|
||||
item.skip();
|
||||
REQUIRE_THROWS(item.skip());
|
||||
@ -114,7 +114,7 @@ TEST_CASE("check alignment issues for fixed64 field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_fixed64(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_fixed64(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -126,7 +126,7 @@ TEST_CASE("write bool field using moved pbf_builder") {
|
||||
|
||||
protozero::pbf_builder<TestBoolean::Test> pw{std::move(pw2)};
|
||||
REQUIRE(pw.valid());
|
||||
REQUIRE_FALSE(pw2.valid()); // NOLINT(hicpp-invalid-access-moved, bugprone-use-after-move)
|
||||
REQUIRE_FALSE(pw2.valid()); // NOLINT(hicpp-invalid-access-moved, bugprone-use-after-move, clang-analyzer-cplusplus.Move)
|
||||
|
||||
SECTION("false") {
|
||||
pw.add_bool(TestBoolean::Test::required_bool_b, false);
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestBoolean::Test msg;
|
||||
|
||||
msg.set_b(0);
|
||||
|
@ -1,21 +1,22 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <test.hpp> // IWYU pragma: keep
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/bool/bool_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write bool field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write bool field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestBoolean::Test msg;
|
||||
|
||||
SECTION("false") {
|
||||
pw.add_bool(1, false);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE_FALSE(msg.b());
|
||||
}
|
||||
@ -23,7 +24,7 @@ TEST_CASE("write bool field and check with libprotobuf") {
|
||||
SECTION("true") {
|
||||
pw.add_bool(1, true);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.b());
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -51,7 +51,7 @@ TEST_CASE("read bytes field: end of buffer") {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_bytes(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_bytes(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestBytes::Test msg;
|
||||
|
||||
msg.set_s("");
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/bytes/bytes_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write bytes field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write bytes field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestBytes::Test msg;
|
||||
|
||||
SECTION("empty") {
|
||||
pw.add_string(1, "");
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.s().empty());
|
||||
}
|
||||
@ -21,7 +22,7 @@ TEST_CASE("write bytes field and check with libprotobuf") {
|
||||
SECTION("one") {
|
||||
pw.add_string(1, "x");
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.s() == "x");
|
||||
}
|
||||
@ -29,7 +30,7 @@ TEST_CASE("write bytes field and check with libprotobuf") {
|
||||
SECTION("string") {
|
||||
pw.add_string(1, "foobar");
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.s() == "foobar");
|
||||
}
|
||||
@ -42,7 +43,7 @@ TEST_CASE("write bytes field and check with libprotobuf") {
|
||||
|
||||
pw.add_string(1, data);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.s().size() == 3);
|
||||
REQUIRE(msg.s()[1] == char(2));
|
||||
|
@ -1,6 +1,12 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <protozero/buffer_fixed.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
|
||||
namespace TestComplex {
|
||||
|
||||
enum class Test : protozero::pbf_tag_type {
|
||||
@ -120,11 +126,7 @@ TEST_CASE("read complex data using pbf_reader: all") {
|
||||
}
|
||||
case 7: {
|
||||
const auto pi = item.get_packed_sint32();
|
||||
int32_t sum = 0;
|
||||
for (auto val : pi) {
|
||||
sum += val;
|
||||
}
|
||||
REQUIRE(sum == 5);
|
||||
REQUIRE(std::accumulate(pi.cbegin(), pi.cend(), 0) == 5);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
@ -265,11 +267,7 @@ TEST_CASE("read complex data using pbf_message: all") {
|
||||
}
|
||||
case TestComplex::Test::packed_sint32_d: {
|
||||
const auto pi = item.get_packed_sint32();
|
||||
int32_t sum = 0;
|
||||
for (auto val : pi) {
|
||||
sum += val;
|
||||
}
|
||||
REQUIRE(sum == 5);
|
||||
REQUIRE(std::accumulate(pi.cbegin(), pi.cend(), 0) == 5);
|
||||
break;
|
||||
}
|
||||
case TestComplex::Test::optional_string_s: {
|
||||
@ -416,7 +414,7 @@ TEST_CASE("write complex data using pbf_writer: all") {
|
||||
pw.add_uint32(4, 66);
|
||||
pw.add_uint32(4, 66);
|
||||
|
||||
const int32_t d[] = { -17, 22 };
|
||||
const std::array<int32_t, 2> d = {{ -17, 22 }};
|
||||
pw.add_packed_sint32(7, std::begin(d), std::end(d));
|
||||
|
||||
pw.add_int64(3, 555555555);
|
||||
@ -453,15 +451,7 @@ TEST_CASE("write complex data using pbf_writer: all") {
|
||||
}
|
||||
case 7: {
|
||||
const auto pi = item.get_packed_sint32();
|
||||
int32_t sum = 0;
|
||||
for (auto val : pi) {
|
||||
sum += val;
|
||||
}
|
||||
REQUIRE(sum == 5);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
REQUIRE(item.get_string() == "optionalstring");
|
||||
REQUIRE(std::accumulate(pi.cbegin(), pi.cend(), 0) == 5);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -577,7 +567,7 @@ TEST_CASE("write complex data using pbf_builder: all") {
|
||||
pw.add_uint32(TestComplex::Test::repeated_uint32_u, 66);
|
||||
pw.add_uint32(TestComplex::Test::repeated_uint32_u, 66);
|
||||
|
||||
const int32_t d[] = { -17, 22 };
|
||||
const std::array<int32_t, 2> d = {{ -17, 22 }};
|
||||
pw.add_packed_sint32(TestComplex::Test::packed_sint32_d, std::begin(d), std::end(d));
|
||||
|
||||
pw.add_int64(TestComplex::Test::optional_int64_j, 555555555);
|
||||
@ -614,15 +604,7 @@ TEST_CASE("write complex data using pbf_builder: all") {
|
||||
}
|
||||
case 7: {
|
||||
const auto pi = item.get_packed_sint32();
|
||||
int32_t sum = 0;
|
||||
for (auto val : pi) {
|
||||
sum += val;
|
||||
}
|
||||
REQUIRE(sum == 5);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
REQUIRE(item.get_string() == "optionalstring");
|
||||
REQUIRE(std::accumulate(pi.cbegin(), pi.cend(), 0) == 5);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -684,3 +666,77 @@ TEST_CASE("write complex with subwriter using pbf_builder") {
|
||||
check_message(buffer_test);
|
||||
}
|
||||
|
||||
TEST_CASE("write complex data using basic_pbf_writer<fixed_size_buffer_adaptor>: all") {
|
||||
std::string data;
|
||||
data.resize(10240);
|
||||
protozero::fixed_size_buffer_adaptor buffer{&*data.begin(), data.size()};
|
||||
protozero::basic_pbf_writer<protozero::fixed_size_buffer_adaptor> pw{buffer};
|
||||
pw.add_fixed32(1, 12345678);
|
||||
|
||||
std::string sdata;
|
||||
sdata.resize(10240);
|
||||
protozero::fixed_size_buffer_adaptor submessage{&*sdata.begin(), sdata.size()};
|
||||
protozero::basic_pbf_writer<protozero::fixed_size_buffer_adaptor> pws{submessage};
|
||||
pws.add_string(1, "foobar");
|
||||
pw.add_message(5, submessage.data(), submessage.size());
|
||||
|
||||
pw.add_uint32(4, 22);
|
||||
pw.add_uint32(4, 44);
|
||||
pw.add_int64(2, -9876543);
|
||||
pw.add_uint32(4, 44);
|
||||
pw.add_uint32(4, 66);
|
||||
pw.add_uint32(4, 66);
|
||||
|
||||
const std::array<int32_t, 2> d = {{ -17, 22 }};
|
||||
pw.add_packed_sint32(7, std::begin(d), std::end(d));
|
||||
|
||||
pw.add_int64(3, 555555555);
|
||||
|
||||
protozero::pbf_reader item{buffer.data(), buffer.size()};
|
||||
|
||||
int number_of_u = 0;
|
||||
while (item.next()) {
|
||||
switch (item.tag()) {
|
||||
case 1: {
|
||||
REQUIRE(item.get_fixed32() == 12345678L);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
REQUIRE(true);
|
||||
item.skip();
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
REQUIRE(item.get_int64() == 555555555LL);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
item.skip();
|
||||
++number_of_u;
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
protozero::pbf_reader subitem = item.get_message();
|
||||
REQUIRE(subitem.next());
|
||||
REQUIRE(subitem.get_string() == "foobar");
|
||||
REQUIRE_FALSE(subitem.next());
|
||||
break;
|
||||
}
|
||||
case 7: {
|
||||
const auto pi = item.get_packed_sint32();
|
||||
REQUIRE(std::accumulate(pi.cbegin(), pi.cend(), 0) == 5);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
REQUIRE(item.get_string() == "optionalstring");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
REQUIRE(false); // should not be here
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
REQUIRE(number_of_u == 5);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestComplex::Test msg;
|
||||
|
||||
msg.set_f(12345678);
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -45,7 +45,7 @@ TEST_CASE("read double field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_double(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_double(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestDouble::Test msg;
|
||||
|
||||
msg.set_x(0.0);
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/double/double_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write double field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write double field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestDouble::Test msg;
|
||||
|
||||
SECTION("zero") {
|
||||
pw.add_double(1, 0.0);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.x() == Approx(0.0));
|
||||
}
|
||||
@ -21,7 +22,7 @@ TEST_CASE("write double field and check with libprotobuf") {
|
||||
SECTION("positive") {
|
||||
pw.add_double(1, 4.893);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.x() == Approx(4.893));
|
||||
}
|
||||
@ -29,7 +30,7 @@ TEST_CASE("write double field and check with libprotobuf") {
|
||||
SECTION("negative") {
|
||||
pw.add_double(1, -9232.33);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.x() == Approx(-9232.33));
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestEnum::Test msg;
|
||||
|
||||
msg.set_color(TestEnum::BLACK);
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/enum/enum_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write enum field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write enum field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestEnum::Test msg;
|
||||
|
||||
SECTION("zero") {
|
||||
pw.add_enum(1, 0L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.color() == TestEnum::Color::BLACK);
|
||||
}
|
||||
@ -21,7 +22,7 @@ TEST_CASE("write enum field and check with libprotobuf") {
|
||||
SECTION("positive") {
|
||||
pw.add_enum(1, 3L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.color() == TestEnum::Color::BLUE);
|
||||
}
|
||||
@ -29,7 +30,7 @@ TEST_CASE("write enum field and check with libprotobuf") {
|
||||
SECTION("negative") {
|
||||
pw.add_enum(1, -1L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.color() == TestEnum::Color::NEG);
|
||||
}
|
||||
@ -37,7 +38,7 @@ TEST_CASE("write enum field and check with libprotobuf") {
|
||||
SECTION("max") {
|
||||
pw.add_enum(1, std::numeric_limits<int32_t>::max() - 1);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.color() == TestEnum::Color::MAX);
|
||||
}
|
||||
@ -45,7 +46,7 @@ TEST_CASE("write enum field and check with libprotobuf") {
|
||||
SECTION("min") {
|
||||
pw.add_enum(1, std::numeric_limits<int32_t>::min() + 1);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.color() == TestEnum::Color::MIN);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestFixed32::Test msg;
|
||||
|
||||
msg.set_i(0);
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/fixed32/fixed32_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write fixed32 field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write fixed32 field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestFixed32::Test msg;
|
||||
|
||||
SECTION("zero") {
|
||||
pw.add_fixed32(1, 0);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == 0);
|
||||
}
|
||||
@ -21,7 +22,7 @@ TEST_CASE("write fixed32 field and check with libprotobuf") {
|
||||
SECTION("max") {
|
||||
pw.add_fixed32(1, std::numeric_limits<uint32_t>::max());
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == std::numeric_limits<uint32_t>::max());
|
||||
}
|
||||
@ -29,7 +30,7 @@ TEST_CASE("write fixed32 field and check with libprotobuf") {
|
||||
SECTION("min") {
|
||||
pw.add_fixed32(1, std::numeric_limits<uint32_t>::min());
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == std::numeric_limits<uint32_t>::min());
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestFixed64::Test msg;
|
||||
|
||||
msg.set_i(0);
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -46,7 +46,7 @@ TEST_CASE("read float field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_float(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_float(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -57,17 +57,17 @@ TEST_CASE("write float field") {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("zero") {
|
||||
pw.add_float(1, 0.0f);
|
||||
pw.add_float(1, 0.0F);
|
||||
REQUIRE(buffer == load_data("float/data-zero"));
|
||||
}
|
||||
|
||||
SECTION("positive") {
|
||||
pw.add_float(1, 5.34f);
|
||||
pw.add_float(1, 5.34F);
|
||||
REQUIRE(buffer == load_data("float/data-pos"));
|
||||
}
|
||||
|
||||
SECTION("negative") {
|
||||
pw.add_float(1, -1.71f);
|
||||
pw.add_float(1, -1.71F);
|
||||
REQUIRE(buffer == load_data("float/data-neg"));
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestFloat::Test msg;
|
||||
|
||||
msg.set_x(0.0);
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestInt32::Test msg;
|
||||
|
||||
msg.set_i(0);
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/int32/int32_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write int32 field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write int32 field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestInt32::Test msg;
|
||||
|
||||
SECTION("zero") {
|
||||
pw.add_int32(1, 0L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == 0L);
|
||||
}
|
||||
@ -21,7 +22,7 @@ TEST_CASE("write int32 field and check with libprotobuf") {
|
||||
SECTION("positive") {
|
||||
pw.add_int32(1, 1L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == 1L);
|
||||
}
|
||||
@ -29,7 +30,7 @@ TEST_CASE("write int32 field and check with libprotobuf") {
|
||||
SECTION("negative") {
|
||||
pw.add_int32(1, -1L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == -1L);
|
||||
}
|
||||
@ -37,7 +38,7 @@ TEST_CASE("write int32 field and check with libprotobuf") {
|
||||
SECTION("max") {
|
||||
pw.add_int32(1, std::numeric_limits<int32_t>::max());
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == std::numeric_limits<int32_t>::max());
|
||||
}
|
||||
@ -45,7 +46,7 @@ TEST_CASE("write int32 field and check with libprotobuf") {
|
||||
SECTION("min") {
|
||||
pw.add_int32(1, std::numeric_limits<int32_t>::min());
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == std::numeric_limits<int32_t>::min());
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestInt64::Test msg;
|
||||
|
||||
msg.set_i(0);
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -6,10 +6,16 @@ TEST_CASE("read message field: string") {
|
||||
|
||||
protozero::pbf_reader item{buffer};
|
||||
|
||||
REQUIRE(item.data().data() == buffer.data());
|
||||
REQUIRE(item.data().size() == buffer.size());
|
||||
|
||||
REQUIRE(item.next());
|
||||
protozero::pbf_reader subitem{item.get_message()};
|
||||
REQUIRE_FALSE(item.next());
|
||||
|
||||
REQUIRE(item.data().data() == buffer.data() + buffer.size());
|
||||
REQUIRE(item.data().empty());
|
||||
|
||||
REQUIRE(subitem.next());
|
||||
REQUIRE(subitem.get_string() == "foobar");
|
||||
REQUIRE_FALSE(subitem.next());
|
||||
@ -21,7 +27,7 @@ TEST_CASE("read message field: end of buffer") {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_string(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_string(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestMessage::Test msg;
|
||||
|
||||
TestMessage::Sub* submsg = msg.mutable_submessage();
|
||||
|
@ -1,28 +1,29 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/message/message_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write message field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write message field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer_test;
|
||||
protozero::pbf_writer pbf_test{buffer_test};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
SECTION("string") {
|
||||
std::string buffer_submessage;
|
||||
protozero::pbf_writer pbf_submessage{buffer_submessage};
|
||||
pbf_submessage.add_string(1, "foobar");
|
||||
|
||||
pbf_test.add_message(1, buffer_submessage);
|
||||
pw.add_message(1, buffer_submessage);
|
||||
}
|
||||
|
||||
SECTION("string with subwriter") {
|
||||
protozero::pbf_writer pbf_submessage{pbf_test, 1};
|
||||
typename TestType::writer_type pbf_submessage{pw, 1};
|
||||
pbf_submessage.add_string(1, "foobar");
|
||||
}
|
||||
|
||||
TestMessage::Test msg;
|
||||
msg.ParseFromString(buffer_test);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
REQUIRE(msg.submessage().s() == "foobar");
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestNested::Test msg;
|
||||
msg.set_i(77);
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/nested/nested_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write nested message fields and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write nested message fields and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer_test;
|
||||
protozero::pbf_writer pbf_test{buffer_test};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
SECTION("string") {
|
||||
std::string buffer_subsub;
|
||||
@ -19,23 +20,23 @@ TEST_CASE("write nested message fields and check with libprotobuf") {
|
||||
pbf_sub.add_string(1, buffer_subsub);
|
||||
pbf_sub.add_int32(2, 88);
|
||||
|
||||
pbf_test.add_message(1, buffer_sub);
|
||||
pw.add_message(1, buffer_sub);
|
||||
}
|
||||
|
||||
SECTION("with subwriter") {
|
||||
protozero::pbf_writer pbf_sub{pbf_test, 1};
|
||||
typename TestType::writer_type pbf_sub{pw, 1};
|
||||
{
|
||||
protozero::pbf_writer pbf_subsub(pbf_sub, 1);
|
||||
typename TestType::writer_type pbf_subsub(pbf_sub, 1);
|
||||
pbf_subsub.add_string(1, "foobar");
|
||||
pbf_subsub.add_int32(2, 99);
|
||||
}
|
||||
pbf_sub.add_int32(2, 88);
|
||||
}
|
||||
|
||||
pbf_test.add_int32(2, 77);
|
||||
pw.add_int32(2, 77);
|
||||
|
||||
TestNested::Test msg;
|
||||
msg.ParseFromString(buffer_test);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i() == 77);
|
||||
REQUIRE(msg.sub().i() == 88);
|
||||
|
@ -48,7 +48,7 @@ TEST_CASE("read repeated fields: end of buffer") {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_int32(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_int32(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeated::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,19 +1,20 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include "t/repeated/repeated_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write repeated fields and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write repeated fields and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestRepeated::Test msg;
|
||||
|
||||
SECTION("one") {
|
||||
pw.add_int32(1, 0L);
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i().size() == 1);
|
||||
REQUIRE(msg.i(0) == 0L);
|
||||
@ -26,7 +27,7 @@ TEST_CASE("write repeated fields and check with libprotobuf") {
|
||||
pw.add_int32(1, std::numeric_limits<int32_t>::max());
|
||||
pw.add_int32(1, std::numeric_limits<int32_t>::min());
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i().size() == 5);
|
||||
REQUIRE(msg.i(0) == 0L);
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
TEST_CASE("read repeated packed bool field: empty") {
|
||||
const std::string buffer = load_data("repeated_packed_bool/data-empty");
|
||||
|
||||
@ -51,7 +53,7 @@ TEST_CASE("read repeated packed bool field: end of buffer") {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_packed_bool(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_packed_bool(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,21 +62,21 @@ TEST_CASE("write repeated packed bool field") {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("empty") {
|
||||
const bool data[] = { true };
|
||||
const std::array<bool, 1> data = {{ true }};
|
||||
pw.add_packed_bool(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_bool/data-empty"));
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
const bool data[] = { true };
|
||||
const std::array<bool, 1> data = {{ true }};
|
||||
pw.add_packed_bool(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_bool/data-one"));
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
const bool data[] = { true, true, false, true };
|
||||
const std::array<bool, 4> data = {{ true, true, false, true }};
|
||||
pw.add_packed_bool(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_bool/data-many"));
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeatedPackedBool::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
TEST_CASE("read repeated packed double field") {
|
||||
// Run these tests twice, the second time we basically move the data
|
||||
// one byte down in the buffer. It doesn't matter how the data or buffer
|
||||
@ -82,7 +84,7 @@ TEST_CASE("read repeated packed double field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_packed_double(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_packed_double(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,21 +95,23 @@ TEST_CASE("write repeated packed double field") {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("empty") {
|
||||
const double data[] = { 17.34 };
|
||||
const std::array<double, 1> data = {{ 17.34 }};
|
||||
pw.add_packed_double(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_double/data-empty"));
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
const double data[] = { 17.34 };
|
||||
const std::array<double, 1> data = {{ 17.34 }};
|
||||
pw.add_packed_double(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_double/data-one"));
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
const double data[] = { 17.34, 0.0, 1.0, std::numeric_limits<double>::min(), std::numeric_limits<double>::max() };
|
||||
const std::array<double, 5> data = {{ 17.34, 0.0, 1.0,
|
||||
std::numeric_limits<double>::min(),
|
||||
std::numeric_limits<double>::max() }};
|
||||
pw.add_packed_double(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_double/data-many"));
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeatedPackedDouble::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
TEST_CASE("read repeated packed enum field: empty") {
|
||||
const std::string buffer = load_data("repeated_packed_enum/data-empty");
|
||||
|
||||
@ -46,7 +48,7 @@ TEST_CASE("read repeated packed enum field: end of buffer") {
|
||||
for (std::string::size_type i = 1; i < buffer.size(); ++i) {
|
||||
protozero::pbf_reader item{buffer.data(), i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_packed_enum(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_packed_enum(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,21 +57,21 @@ TEST_CASE("write repeated packed enum field") {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("empty") {
|
||||
const int32_t data[] = { 0 /* BLACK */ };
|
||||
const std::array<int32_t, 1> data = {{ 0 /* BLACK */ }};
|
||||
pw.add_packed_enum(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_enum/data-empty"));
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
const int32_t data[] = { 0 /* BLACK */ };
|
||||
const std::array<int32_t, 1> data = {{ 0 /* BLACK */ }};
|
||||
pw.add_packed_enum(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_enum/data-one"));
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
const int32_t data[] = { 0 /* BLACK */, 3 /* BLUE */, 2 /* GREEN */ };
|
||||
const std::array<int32_t, 3> data = {{ 0 /* BLACK */, 3 /* BLUE */, 2 /* GREEN */ }};
|
||||
pw.add_packed_enum(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_enum/data-many"));
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeatedPackedEnum::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,3 +1,4 @@
|
||||
syntax = "proto2";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeatedPackedFixed32::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,35 +1,39 @@
|
||||
|
||||
#include <test.hpp>
|
||||
#include <buffer.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
|
||||
#include "t/repeated_packed_fixed32/repeated_packed_fixed32_testcase.pb.h"
|
||||
|
||||
TEST_CASE("write repeated packed fixed32 field and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write repeated packed fixed32 field and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestRepeatedPackedFixed32::Test msg;
|
||||
|
||||
SECTION("empty") {
|
||||
uint32_t data[] = { 17UL };
|
||||
const std::array<uint32_t, 1> data = {{ 17UL }};
|
||||
pw.add_packed_fixed32(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
uint32_t data[] = { 17UL };
|
||||
const std::array<uint32_t, 1> data = {{ 17UL }};
|
||||
pw.add_packed_fixed32(1, std::begin(data), std::end(data));
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i().size() == 1);
|
||||
REQUIRE(msg.i(0) == 17UL);
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
uint32_t data[] = { 17UL, 0UL, 1UL, std::numeric_limits<uint32_t>::max() };
|
||||
const std::array<uint32_t, 4> data = {{ 17UL, 0UL, 1UL, std::numeric_limits<uint32_t>::max() }};
|
||||
pw.add_packed_fixed32(1, std::begin(data), std::end(data));
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i().size() == 4);
|
||||
REQUIRE(msg.i(0) == 17UL);
|
||||
@ -39,17 +43,18 @@ TEST_CASE("write repeated packed fixed32 field and check with libprotobuf") {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("write from different types of iterators and check with libprotobuf") {
|
||||
TEMPLATE_TEST_CASE("write from different types of iterators and check with libprotobuf", "",
|
||||
buffer_test_string, buffer_test_vector, buffer_test_array, buffer_test_external) {
|
||||
|
||||
std::string buffer;
|
||||
protozero::pbf_writer pw{buffer};
|
||||
TestType buffer;
|
||||
typename TestType::writer_type pw{buffer.buffer()};
|
||||
|
||||
TestRepeatedPackedFixed32::Test msg;
|
||||
|
||||
SECTION("from uint16_t") {
|
||||
uint16_t data[] = { 1, 4, 9, 16, 25 };
|
||||
const std::array<uint16_t, 5> data = {{ 1, 4, 9, 16, 25 }};
|
||||
|
||||
pw.add_packed_fixed32(1, std::begin(data), std::end(data));
|
||||
pw.template add_packed_fixed<uint32_t>(1, std::begin(data), std::end(data));
|
||||
}
|
||||
|
||||
SECTION("from string") {
|
||||
@ -59,10 +64,10 @@ TEST_CASE("write from different types of iterators and check with libprotobuf")
|
||||
std::istream_iterator<uint32_t> eod;
|
||||
std::istream_iterator<uint32_t> it(sdata);
|
||||
|
||||
pw.add_packed_fixed32(1, it, eod);
|
||||
pw.template add_packed_fixed<uint32_t>(1, it, eod);
|
||||
}
|
||||
|
||||
msg.ParseFromString(buffer);
|
||||
msg.ParseFromArray(buffer.data(), buffer.size());
|
||||
|
||||
REQUIRE(msg.i().size() == 5);
|
||||
REQUIRE(msg.i(0) == 1);
|
||||
|
@ -1,8 +1,9 @@
|
||||
|
||||
#include <testcase.hpp>
|
||||
|
||||
#include "testcase.pb.h"
|
||||
|
||||
int main(int c, char *argv[]) {
|
||||
int main() {
|
||||
TestRepeatedPackedFixed64::Test msg;
|
||||
|
||||
write_to_file(msg, "data-empty.pbf");
|
||||
|
@ -1,6 +1,8 @@
|
||||
|
||||
#include <test.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
TEST_CASE("read repeated packed float field") {
|
||||
// Run these tests twice, the second time we basically move the data
|
||||
// one byte down in the buffer. It doesn't matter how the data or buffer
|
||||
@ -28,7 +30,7 @@ TEST_CASE("read repeated packed float field") {
|
||||
auto it_range = item.get_packed_float();
|
||||
REQUIRE_FALSE(item.next());
|
||||
|
||||
REQUIRE(*it_range.begin() == Approx(17.34f));
|
||||
REQUIRE(*it_range.begin() == Approx(17.34F));
|
||||
REQUIRE(std::next(it_range.begin()) == it_range.end());
|
||||
}
|
||||
|
||||
@ -41,9 +43,9 @@ TEST_CASE("read repeated packed float field") {
|
||||
REQUIRE_FALSE(item.next());
|
||||
|
||||
auto it = it_range.begin();
|
||||
REQUIRE(*it++ == Approx(17.34f));
|
||||
REQUIRE(*it++ == Approx( 0.0f));
|
||||
REQUIRE(*it++ == Approx( 1.0f));
|
||||
REQUIRE(*it++ == Approx(17.34F));
|
||||
REQUIRE(*it++ == Approx( 0.0F));
|
||||
REQUIRE(*it++ == Approx( 1.0F));
|
||||
REQUIRE(*it++ == std::numeric_limits<float>::min());
|
||||
REQUIRE(*it++ == std::numeric_limits<float>::max());
|
||||
REQUIRE(it == it_range.end());
|
||||
@ -55,7 +57,7 @@ TEST_CASE("read repeated packed float field") {
|
||||
for (std::string::size_type i = 1; i < abuffer.size() - n; ++i) {
|
||||
protozero::pbf_reader item{abuffer.data() + n, i};
|
||||
REQUIRE(item.next());
|
||||
REQUIRE_THROWS_AS(item.get_packed_float(), const protozero::end_of_buffer_exception&);
|
||||
REQUIRE_THROWS_AS(item.get_packed_float(), protozero::end_of_buffer_exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,21 +68,21 @@ TEST_CASE("write repeated packed float field") {
|
||||
protozero::pbf_writer pw{buffer};
|
||||
|
||||
SECTION("empty") {
|
||||
float data[] = { 17.34f };
|
||||
const std::array<float, 1> data = {{ 17.34F }};
|
||||
pw.add_packed_float(1, std::begin(data), std::begin(data) /* !!!! */);
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_float/data-empty"));
|
||||
}
|
||||
|
||||
SECTION("one") {
|
||||
float data[] = { 17.34f };
|
||||
const std::array<float, 1> data = {{ 17.34F }};
|
||||
pw.add_packed_float(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_float/data-one"));
|
||||
}
|
||||
|
||||
SECTION("many") {
|
||||
float data[] = { 17.34f, 0.0f, 1.0f, std::numeric_limits<float>::min(), std::numeric_limits<float>::max() };
|
||||
const std::array<float, 5> data = {{ 17.34F, 0.0F, 1.0F, std::numeric_limits<float>::min(), std::numeric_limits<float>::max() }};
|
||||
pw.add_packed_float(1, std::begin(data), std::end(data));
|
||||
|
||||
REQUIRE(buffer == load_data("repeated_packed_float/data-many"));
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user