Merge commit '68019a1fb20928beaa7b0cb2d8310af29ffe789e' as 'third_party/protozero'
This commit is contained in:
		
						commit
						ba92674c6e
					
				
							
								
								
									
										34
									
								
								third_party/protozero/.clang-tidy
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								third_party/protozero/.clang-tidy
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
---
 | 
			
		||||
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'
 | 
			
		||||
#
 | 
			
		||||
#  Disabled checks:
 | 
			
		||||
#
 | 
			
		||||
#  cert-dcl21-cpp
 | 
			
		||||
#    It is unclear whether this is still a good recommendation in modern C++.
 | 
			
		||||
#
 | 
			
		||||
#  cert-err60-cpp
 | 
			
		||||
#    Reports std::runtime_error as broken which we can't do anything about.
 | 
			
		||||
#
 | 
			
		||||
#  cppcoreguidelines-pro-bounds-array-to-pointer-decay
 | 
			
		||||
#    Limited use and many false positives including for all asserts.
 | 
			
		||||
#
 | 
			
		||||
#  cppcoreguidelines-pro-bounds-pointer-arithmetic
 | 
			
		||||
#    This is a low-level library, it needs to do pointer arithmetic.
 | 
			
		||||
#
 | 
			
		||||
#  cppcoreguidelines-pro-type-reinterpret-cast
 | 
			
		||||
#    This is a low-level library, it needs to do reinterpret-casts.
 | 
			
		||||
#
 | 
			
		||||
#  fuchsia-*
 | 
			
		||||
#    Much too strict.
 | 
			
		||||
#
 | 
			
		||||
#  google-runtime-references
 | 
			
		||||
#    This is just a matter of preference, and we can't change the interfaces
 | 
			
		||||
#    now anyways.
 | 
			
		||||
#
 | 
			
		||||
#  hicpp-no-array-decay
 | 
			
		||||
#    Limited use and many false positives including for all asserts.
 | 
			
		||||
#
 | 
			
		||||
WarningsAsErrors: '*'
 | 
			
		||||
HeaderFilterRegex: '\/include\/'
 | 
			
		||||
AnalyzeTemporaryDtors: false
 | 
			
		||||
...
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/.gitattributes
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
*.pbf -text
 | 
			
		||||
							
								
								
									
										178
									
								
								third_party/protozero/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								third_party/protozero/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,178 @@
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Configuration for continuous integration service at travis-ci.org
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
language: generic
 | 
			
		||||
 | 
			
		||||
sudo: false
 | 
			
		||||
 | 
			
		||||
dist: trusty
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
# Save common build configurations as shortcuts, so we can reference them later.
 | 
			
		||||
addons_shortcuts:
 | 
			
		||||
  addons_clang35: &clang35
 | 
			
		||||
    apt:
 | 
			
		||||
      sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-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' ]
 | 
			
		||||
  addons_clang39: &clang39
 | 
			
		||||
    apt:
 | 
			
		||||
      sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-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' ]
 | 
			
		||||
  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
 | 
			
		||||
    apt:
 | 
			
		||||
      sources: [ 'ubuntu-toolchain-r-test' ]
 | 
			
		||||
      packages: [ 'libprotobuf-dev','protobuf-compiler', 'g++-4.7', 'gcc-4.7' ]
 | 
			
		||||
  addons_gcc48: &gcc48
 | 
			
		||||
    apt:
 | 
			
		||||
      sources: [ 'ubuntu-toolchain-r-test' ]
 | 
			
		||||
      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' ]
 | 
			
		||||
  addons_gcc5: &gcc5
 | 
			
		||||
    apt:
 | 
			
		||||
      sources: [ 'ubuntu-toolchain-r-test' ]
 | 
			
		||||
      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' ]
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
  include:
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-3.5"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-3.5 CXX=clang++-3.5
 | 
			
		||||
      addons: *clang35
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-3.8"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-3.8 CXX=clang++-3.8
 | 
			
		||||
      addons: *clang38
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-3.9"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-3.9 CXX=clang++-3.9
 | 
			
		||||
      addons: *clang39
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-4.0"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-4.0 CXX=clang++-4.0
 | 
			
		||||
      addons: *clang40
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-5.0"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0
 | 
			
		||||
           CLANG_TIDY=clang-tidy-5.0
 | 
			
		||||
      addons: *clang50
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-5.0"
 | 
			
		||||
      env: BUILD='Release' CC=clang-5.0 CXX=clang++-5.0
 | 
			
		||||
      addons: *clang50
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "clang-5.0"
 | 
			
		||||
      env: BUILD='Debug' CC=clang-5.0 CXX=clang++-5.0
 | 
			
		||||
           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
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-4.7"
 | 
			
		||||
      env: BUILD='Debug' CC=gcc-4.7 CXX=g++-4.7
 | 
			
		||||
      addons: *gcc47
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-4.8"
 | 
			
		||||
      env: BUILD='Debug' CC=gcc-4.8 CXX=g++-4.8
 | 
			
		||||
      addons: *gcc48
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-4.9"
 | 
			
		||||
      env: BUILD='Debug' CC=gcc-4.9 CXX=g++-4.9
 | 
			
		||||
           COVERAGE=gcov-4.9
 | 
			
		||||
           CXXFLAGS="--coverage" LDFLAGS="--coverage"
 | 
			
		||||
      addons: *gcc49
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-5"
 | 
			
		||||
      env: BUILD='Debug' CC=gcc-5 CXX=g++-5
 | 
			
		||||
           CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=0"
 | 
			
		||||
      addons: *gcc5
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-5"
 | 
			
		||||
      env: BUILD='Debug' CC=gcc-5 CXX=g++-5
 | 
			
		||||
           CXXFLAGS="-D_GLIBCXX_USE_CXX11_ABI=1"
 | 
			
		||||
      addons: *gcc5
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-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
 | 
			
		||||
    - os: linux
 | 
			
		||||
      compiler: "gcc-6"
 | 
			
		||||
      env: BUILD='Release' CC=gcc-6 CXX=g++-6
 | 
			
		||||
      addons: *gcc6
 | 
			
		||||
    - os: osx
 | 
			
		||||
      osx_image: xcode6.4
 | 
			
		||||
      compiler: clang
 | 
			
		||||
      env: BUILD='Debug'
 | 
			
		||||
    - os: osx
 | 
			
		||||
      osx_image: xcode7.3
 | 
			
		||||
      compiler: clang
 | 
			
		||||
      env: BUILD='Debug'
 | 
			
		||||
    - os: osx
 | 
			
		||||
      osx_image: xcode8.3
 | 
			
		||||
      compiler: clang
 | 
			
		||||
      env: BUILD='Debug'
 | 
			
		||||
    - os: osx
 | 
			
		||||
      osx_image: xcode9.1
 | 
			
		||||
      compiler: clang
 | 
			
		||||
      env: BUILD='Debug'
 | 
			
		||||
    - os: osx
 | 
			
		||||
      osx_image: xcode9.1
 | 
			
		||||
      compiler: clang
 | 
			
		||||
      env: BUILD='Release'
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - if [[ $(uname -s) == 'Darwin' ]]; then
 | 
			
		||||
      brew update;
 | 
			
		||||
      brew install protobuf;
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - mkdir build
 | 
			
		||||
  - cd build
 | 
			
		||||
  - cmake .. -LA -DCMAKE_BUILD_TYPE=${BUILD} -DPROTOZERO_DATA_VIEW=$PROTOZERO_DATA_VIEW -DCLANG_TIDY=$(which ${CLANG_TIDY})
 | 
			
		||||
  - make VERBOSE=1
 | 
			
		||||
  - ctest --output-on-failure
 | 
			
		||||
  - if [ -n "${CLANG_TIDY}" ]; then make clang-tidy; fi
 | 
			
		||||
  - |
 | 
			
		||||
    if [ -n "${COVERAGE}" ]; then
 | 
			
		||||
      which ${COVERAGE}
 | 
			
		||||
      curl -S -f https://codecov.io/bash -o codecov
 | 
			
		||||
      chmod +x codecov
 | 
			
		||||
      ${COVERAGE} -p $(find test/ tools/ -name '*.o')
 | 
			
		||||
      ./codecov -Z -f '*protozero*' -f '*tools*' -f '!*catch*' -X search
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										324
									
								
								third_party/protozero/CHANGELOG.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								third_party/protozero/CHANGELOG.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,324 @@
 | 
			
		||||
 | 
			
		||||
# 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/).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [unreleased] -
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.6.2] - 2018-03-09
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Update included catch.hpp to v1.12.0.
 | 
			
		||||
- Move basic unit tests into their own directory (`test/unit`).
 | 
			
		||||
- Improved clang-tidy config and fixed some code producing warnings.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Buffer overflow in pbf-decoder tool.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.6.1] - 2017-11-16
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Document internal handling of varints.
 | 
			
		||||
- Add aliases for fixed iterators, too.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- The `const_fixed_iterator` is now a random access iterator making code
 | 
			
		||||
  using it potentially more performant (for instance when using
 | 
			
		||||
  `std::distance`)
 | 
			
		||||
- Overloads `std::distance` for the varint and svarint iterators. This is
 | 
			
		||||
  better than the workaround with the `rage_size` function used before.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Rename `.proto` files in some tests to be unique. This solves a problem
 | 
			
		||||
  when building with newer versions of the Google Protobuf library.
 | 
			
		||||
- Floating point comparisons in tests are now always correctly done using
 | 
			
		||||
  `Approx()`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.6.0] - 2017-10-24
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Comparison functions (<, <=, >, >=) for `data_view`. Allows use in `std::map`
 | 
			
		||||
  for instance.
 | 
			
		||||
- Tool `pbf-decoder` for decoding raw messages. This has limited use for
 | 
			
		||||
  normal users, but it can be used for fuzzing.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Protozero now uses CMake to build the tests etc. This does not affect
 | 
			
		||||
  simple users of the library, but if you are using CMake yourself you might
 | 
			
		||||
  want to use the `cmake/FindProtozero.cmake` module provided. The README
 | 
			
		||||
  contains more information about build options.
 | 
			
		||||
- Moved `data_view` class from `types.hpp` into its own header file
 | 
			
		||||
  `data_view.hpp`.
 | 
			
		||||
- Implementation of the `const_fixed_iterator` to use only a single pointer
 | 
			
		||||
  instead of two.
 | 
			
		||||
- Made `operator==` and `operator!=` on `data_view` constexpr.
 | 
			
		||||
- The `pbf_reader` constructor taking a `std::pair` is deprecated. Use one
 | 
			
		||||
  of the other constructors instead.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Varints where the last byte was larger than what would fit in 64bit were
 | 
			
		||||
  triggering undefined behaviour. This can only happen when the message
 | 
			
		||||
  being decoded was corrupt in some way.
 | 
			
		||||
- Do not assert when reading too long varints for bools any more. A valid
 | 
			
		||||
  encoder should never generate varints with more than one byte for bools,
 | 
			
		||||
  but if they are longer that's not really a problem, so just handle it.
 | 
			
		||||
- Throw exception if the length of a packed repeated field of a fixed-length
 | 
			
		||||
  type is invalid. The length must always be a multiple of the size of the
 | 
			
		||||
  underlying type. This can only happen if the data is corrupted in some way,
 | 
			
		||||
  a valid encoder would never generate data like this.
 | 
			
		||||
- Throw an exception when reading invalid tags. This can only happen if the
 | 
			
		||||
  data is corrupted in some way, a valid encoder would never generate invalid
 | 
			
		||||
  tags.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.5.3] - 2017-09-22
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- More documentation.
 | 
			
		||||
- New `size()` method on iterator range used for packed repeated fields to
 | 
			
		||||
  find out how many elements there are in the range. This is much faster
 | 
			
		||||
  compared to the `std::difference()` call you had to do before, because the
 | 
			
		||||
  varints don't have to be fully decoded. See [Advanced
 | 
			
		||||
  Topics](doc/advanced.md) for details.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Updated clang-tidy settings in Makefiles and fixed a lot of minor issues
 | 
			
		||||
  reported by clang-tidy.
 | 
			
		||||
- Update included catch.hpp to version 1.10.0.
 | 
			
		||||
- Miscellaneous code cleanups.
 | 
			
		||||
- Support for invalid state in `pbf_writer` and `packed_repeated_fields`.
 | 
			
		||||
  This fixes move construction and move assignement in `pbf_writer` and
 | 
			
		||||
  disables the copy construction and copy assignement which don't have
 | 
			
		||||
  clear semantics. It introduces an invalid or empty state in the
 | 
			
		||||
  `pbf_writer`, `pbf_builder`, and `packed_repeated_fields` classes used for
 | 
			
		||||
  default-constructed, moved from, or committed objects. There is a new
 | 
			
		||||
  `commit()` function for `pbf_writer` and the `packed_repeated_fields` which
 | 
			
		||||
  basically does the same as the destructor but can be called explicitly.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- The `empty()` method of the iterator range now returns a `bool` instead of
 | 
			
		||||
  a `size_t`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.5.2] - 2017-06-30
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Add missing two-parameter version of `pbf_message::next()` function.
 | 
			
		||||
- Add `data_view::empty()` function.
 | 
			
		||||
- Add missing versions of `add_bytes()`, `add_string()`, and `add_message()`
 | 
			
		||||
  to `pbf_builder`.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Clarify include file usage in tutorial.
 | 
			
		||||
- Updated included Catch unit test framework to version 1.9.6 and updated
 | 
			
		||||
  tests to work with the current version.
 | 
			
		||||
- Make some constructors explicit (best practice to avoid silent conversions).
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Important bugfix in `data_view` equality operator. The equality operator is
 | 
			
		||||
  actually never used in the protozero code itself, but users of protozero
 | 
			
		||||
  might use it. This is a serious bug that could lead to buffer overrun type
 | 
			
		||||
  problems.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.5.1] - 2017-01-14
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Better documentation for `tag_and_type()` in doc/advanced.md.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Fixed broken "make doc" build.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.5.0] - 2017-01-12
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Add `add_bytes_vectored()` methods to `pbf_writer` and `pbf_builder`. This
 | 
			
		||||
  allows single-copy scatter-gather type adding of data that has been prepared
 | 
			
		||||
  in pieces to a protobuf message.
 | 
			
		||||
- New functions to check the tag and wire type at the same time: Two parameter
 | 
			
		||||
  version of `pbf_reader::next()` and `pbf_reader::tag_and_type()` can be used
 | 
			
		||||
  together with the free function `tag_and_type()` to easily and quickly check
 | 
			
		||||
  that not only the tag but also the wire type is correct for a field.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- `packed_field_*` classes now work with `pbf_builder`.
 | 
			
		||||
- Reorganized documentation. Advanced docs are now under doc/advanced.md.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- `packed_field` class is now non-copyable because data can get corrupted if
 | 
			
		||||
  you copy it around.
 | 
			
		||||
- Comparison operators of `data_view` now have const& parameters.
 | 
			
		||||
- Make zigzag encoding/decoding functions constexpr.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.4.5] - 2016-11-18
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Undefined behaviour in packed fixed iterator. As a result, the macro
 | 
			
		||||
  `PROTOZERO_DO_NOT_USE_BARE_POINTER` is not used any more.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.4.4] - 2016-11-15
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Byteswap implementation.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.4.3] - 2016-11-15
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Undefined behaviour in byte swapping code.
 | 
			
		||||
- Rename some parameters to avoid "shadow" warning from some compilers.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.4.2] - 2016-08-27
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Compile fix: Variable shadowing.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.4.1] - 2016-08-21
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- GCC 4.8 compile fixed
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- New ability to dynamically require the module as a node module to ease
 | 
			
		||||
  building against from other node C++ modules.
 | 
			
		||||
 | 
			
		||||
## [1.4.0] - 2016-07-22
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Use more efficient new `skip_varint()` function when iterating over
 | 
			
		||||
  packed varints.
 | 
			
		||||
- Split `decode_varint()` function into two functions speeding up the
 | 
			
		||||
  common case where a varint is only one byte long.
 | 
			
		||||
- Introduce new class `iterator_range` used instead of `std::pair` of
 | 
			
		||||
  iterators. This way the objects can be used in range-based for loops.
 | 
			
		||||
  Read UPGRADING.md for details.
 | 
			
		||||
- Introduce new class `data_view` and functions using and returning it.
 | 
			
		||||
  Read UPGRADING.md for details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.3.0] - 2016-02-18
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Added `config.hpp` header which now includes all the macro magic to
 | 
			
		||||
  configure the library for different architectures etc.
 | 
			
		||||
- New way to create repeated packed fields without using an iterator.
 | 
			
		||||
- Add `rollback()` function to `pbf_writer` for "manual" rollback.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Various test and documentation cleanups.
 | 
			
		||||
- Rename `pbf_types.hpp` to `types.hpp`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.2.3] - 2015-11-30
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- Added `config.hpp` header which now includes all the macro magic to
 | 
			
		||||
  configure the library for different architectures etc.
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Unaligned access to floats/doubles on some ARM architectures.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.2.2] - 2015-10-13
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Fix the recently broken writing of bools on big-endian architectures.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.2.1] - 2015-10-12
 | 
			
		||||
 | 
			
		||||
### Fixed
 | 
			
		||||
 | 
			
		||||
- Removed unneeded code (1-byte "swap") which lead to test failures.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.2.0] - 2015-10-08
 | 
			
		||||
 | 
			
		||||
### Added
 | 
			
		||||
 | 
			
		||||
- `pbf_message` and `pbf_builder` template classes wrapping `pbf_reader`
 | 
			
		||||
  and `pbf_writer`, respectively. The new classes are the preferred
 | 
			
		||||
  interface now.
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Improved byte swapping operation.
 | 
			
		||||
- Detect some types of data corruption earlier and throw.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## [1.1.0] - 2015-08-22
 | 
			
		||||
 | 
			
		||||
### Changed
 | 
			
		||||
 | 
			
		||||
- Make pbf reader and writer code endianess-aware.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[unreleased]: https://github.com/osmcode/libosmium/compare/v1.6.2...HEAD
 | 
			
		||||
[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
 | 
			
		||||
[1.5.3]: https://github.com/osmcode/libosmium/compare/v1.5.2...v1.5.3
 | 
			
		||||
[1.5.2]: https://github.com/osmcode/libosmium/compare/v1.5.1...v1.5.2
 | 
			
		||||
[1.5.1]: https://github.com/osmcode/libosmium/compare/v1.5.0...v1.5.1
 | 
			
		||||
[1.5.0]: https://github.com/osmcode/libosmium/compare/v1.4.5...v1.5.0
 | 
			
		||||
[1.4.5]: https://github.com/osmcode/libosmium/compare/v1.4.4...v1.4.5
 | 
			
		||||
[1.4.4]: https://github.com/osmcode/libosmium/compare/v1.4.3...v1.4.4
 | 
			
		||||
[1.4.3]: https://github.com/osmcode/libosmium/compare/v1.4.2...v1.4.3
 | 
			
		||||
[1.4.2]: https://github.com/osmcode/libosmium/compare/v1.4.1...v1.4.2
 | 
			
		||||
[1.4.1]: https://github.com/osmcode/libosmium/compare/v1.4.0...v1.4.1
 | 
			
		||||
[1.4.0]: https://github.com/osmcode/libosmium/compare/v1.3.0...v1.4.0
 | 
			
		||||
[1.3.0]: https://github.com/osmcode/libosmium/compare/v1.2.3...v1.3.0
 | 
			
		||||
[1.2.3]: https://github.com/osmcode/libosmium/compare/v1.2.2...v1.2.3
 | 
			
		||||
[1.2.2]: https://github.com/osmcode/libosmium/compare/v1.2.1...v1.2.2
 | 
			
		||||
[1.2.1]: https://github.com/osmcode/libosmium/compare/v1.2.0...v1.2.1
 | 
			
		||||
[1.2.0]: https://github.com/osmcode/libosmium/compare/v1.1.0...v1.2.0
 | 
			
		||||
[1.1.0]: https://github.com/osmcode/libosmium/compare/v1.0.0...v1.1.0
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										145
									
								
								third_party/protozero/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								third_party/protozero/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  CMake config
 | 
			
		||||
#
 | 
			
		||||
#  protozero
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cmake_minimum_required(VERSION 2.8 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}")
 | 
			
		||||
 | 
			
		||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
option(WERROR "Add -Werror flag to build (turns warnings into errors)" ON)
 | 
			
		||||
 | 
			
		||||
if(MSVC)
 | 
			
		||||
    add_definitions(-std=c++11 /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)
 | 
			
		||||
    if(WERROR)
 | 
			
		||||
        add_definitions(-Werror)
 | 
			
		||||
    endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
include_directories("${CMAKE_SOURCE_DIR}/include")
 | 
			
		||||
 | 
			
		||||
set(PROTOZERO_DATA_VIEW "" CACHE STRING "Type used for protozero::data_view")
 | 
			
		||||
if(NOT PROTOZERO_DATA_VIEW STREQUAL "")
 | 
			
		||||
    add_definitions(-DPROTOZERO_DATA_VIEW=${PROTOZERO_DATA_VIEW})
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Find dependencies
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
find_package(Protobuf)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Optional "clang-tidy" target
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
message(STATUS "Looking for clang-tidy")
 | 
			
		||||
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0 clang-tidy-5.0)
 | 
			
		||||
 | 
			
		||||
if(CLANG_TIDY)
 | 
			
		||||
    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/unit/*.cpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/tools/*.cpp
 | 
			
		||||
    )
 | 
			
		||||
    add_dependencies(clang-tidy writer_tests)
 | 
			
		||||
else()
 | 
			
		||||
    message(STATUS "Looking for clang-tidy - not found")
 | 
			
		||||
    message(STATUS "  Build target 'clang-tidy' will not be available.")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Optional "cppcheck" target
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
message(STATUS "Looking for cppcheck")
 | 
			
		||||
find_program(CPPCHECK NAMES cppcheck)
 | 
			
		||||
 | 
			
		||||
if(CPPCHECK)
 | 
			
		||||
    message(STATUS "Looking for cppcheck - found")
 | 
			
		||||
    add_custom_target(cppcheck
 | 
			
		||||
        ${CPPCHECK}
 | 
			
		||||
        -Uassert --std=c++11 --enable=all
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/include/protozero/*.hpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/test/*.cpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/test/include/*.hpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/test/t/*/*.cpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/test/unit/*.cpp
 | 
			
		||||
        ${CMAKE_SOURCE_DIR}/tools/*.cpp
 | 
			
		||||
    )
 | 
			
		||||
else()
 | 
			
		||||
    message(STATUS "Looking for cppcheck - not found")
 | 
			
		||||
    message(STATUS "  Build target 'cppcheck' will not be available.")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Include what you use
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
message(STATUS "Looking for iwyu")
 | 
			
		||||
find_program(IWYU_TOOL NAMES iwyu_tool)
 | 
			
		||||
 | 
			
		||||
if(IWYU_TOOL)
 | 
			
		||||
    message(STATUS "Looking for iwyu - found")
 | 
			
		||||
    add_custom_target(iwyu
 | 
			
		||||
        ${IWYU_TOOL} -p ${CMAKE_BINARY_DIR}
 | 
			
		||||
    )
 | 
			
		||||
else()
 | 
			
		||||
    message(STATUS "Looking for iwyu - not found")
 | 
			
		||||
    message(STATUS "  Build target 'iwyu' will not be available.")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Installation
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
install(DIRECTORY include/protozero DESTINATION include)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
enable_testing()
 | 
			
		||||
 | 
			
		||||
add_subdirectory(doc)
 | 
			
		||||
 | 
			
		||||
add_subdirectory(tools)
 | 
			
		||||
 | 
			
		||||
add_subdirectory(test)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										21
									
								
								third_party/protozero/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								third_party/protozero/CONTRIBUTING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
# Contributing to protozero
 | 
			
		||||
 | 
			
		||||
## Releasing
 | 
			
		||||
 | 
			
		||||
To release a new protozero version:
 | 
			
		||||
 | 
			
		||||
 - Make sure all tests are passing locally, on travis and on appveyor
 | 
			
		||||
 - Make sure "make doc" builds
 | 
			
		||||
 - Update version number in
 | 
			
		||||
   - include/protozero/version.hpp (two places)
 | 
			
		||||
   - CMakeLists.txt (one place)
 | 
			
		||||
 - Update CHANGELOG.md
 | 
			
		||||
   (don't forget links at the bottom of the file)
 | 
			
		||||
 - Update UPGRADING.md if necessary
 | 
			
		||||
 - `git commit -m "Release X.Y.Z" include/protozero/version.hpp CMakeLists.txt CHANGELOG.md UPGRADING.md`
 | 
			
		||||
 - `git tag vX.Y.Z`
 | 
			
		||||
 - `git push`
 | 
			
		||||
 - `git push --tags`
 | 
			
		||||
 - Go to https://github.com/mapbox/protozero/releases
 | 
			
		||||
   and edit the new release. Put "Version x.y.z" in title and
 | 
			
		||||
   cut-and-paste entry from CHANGELOG.md.
 | 
			
		||||
							
								
								
									
										22
									
								
								third_party/protozero/FUZZING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								third_party/protozero/FUZZING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
 | 
			
		||||
To do fuzz testing using [AFL](http://lcamtuf.coredump.cx/afl/) compile with
 | 
			
		||||
the AFL compiler wrappers:
 | 
			
		||||
 | 
			
		||||
    mkdir build
 | 
			
		||||
    cd build
 | 
			
		||||
    CC=afl-clang CXX=afl-clang++ cmake ..
 | 
			
		||||
    mkdir testcase_dir
 | 
			
		||||
 | 
			
		||||
You need some data to start the fuzzing. In this case I am using all the test
 | 
			
		||||
messages from the unit tests:
 | 
			
		||||
 | 
			
		||||
    find ../test/t/ -name data-\*.pbf -a -not -empty -exec cp {} testcase_dir/ \;
 | 
			
		||||
 | 
			
		||||
Then do the actual fuzzing:
 | 
			
		||||
 | 
			
		||||
    afl-fuzz -i testcase_dir -o findings_dir -- tools/pbf-decoder -
 | 
			
		||||
 | 
			
		||||
See the AFL documentation for more information.
 | 
			
		||||
 | 
			
		||||
This only checkes the reading side of Protozero!
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										177
									
								
								third_party/protozero/LICENSE.from_folly
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								third_party/protozero/LICENSE.from_folly
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,177 @@
 | 
			
		||||
 | 
			
		||||
                                 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
							
								
								
									
										24
									
								
								third_party/protozero/LICENSE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								third_party/protozero/LICENSE.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
protozero copyright (c) Mapbox.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions are
 | 
			
		||||
met:
 | 
			
		||||
 | 
			
		||||
    * Redistributions of source code must retain the above copyright
 | 
			
		||||
      notice, this list of conditions and the following disclaimer.
 | 
			
		||||
    * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
      notice, this list of conditions and the following disclaimer in
 | 
			
		||||
      the documentation and/or other materials provided with the
 | 
			
		||||
      distribution.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 | 
			
		||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
			
		||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
			
		||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
			
		||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
			
		||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
			
		||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
							
								
								
									
										156
									
								
								third_party/protozero/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								third_party/protozero/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,156 @@
 | 
			
		||||
# protozero
 | 
			
		||||
 | 
			
		||||
Minimalistic protocol buffer decoder and encoder in C++.
 | 
			
		||||
 | 
			
		||||
Designed for high performance. Suitable for writing zero copy parsers and
 | 
			
		||||
encoders with minimal need for run-time allocation of memory.
 | 
			
		||||
 | 
			
		||||
Low-level: this is designed to be a building block for writing a very
 | 
			
		||||
customized decoder for a stable protobuf schema. If your protobuf schema is
 | 
			
		||||
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://ci.appveyor.com/project/Mapbox/protozero)
 | 
			
		||||
[](https://codecov.io/gh/mapbox/protozero)
 | 
			
		||||
[](https://repology.org/metapackage/protozero)
 | 
			
		||||
 | 
			
		||||
## Depends
 | 
			
		||||
 | 
			
		||||
* C++11 compiler
 | 
			
		||||
* CMake
 | 
			
		||||
* Some tests depend on the Google Protobuf library, but use of Protozero
 | 
			
		||||
  doesn't need it
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## How it works
 | 
			
		||||
 | 
			
		||||
The protozero code does **not** read `.proto` files used by the usual Protobuf
 | 
			
		||||
implementations. The developer using protozero has to manually "translate" the
 | 
			
		||||
`.proto` description into code. This means there is no way to access any of the
 | 
			
		||||
information from the `.proto` description. This results in a few restrictions:
 | 
			
		||||
 | 
			
		||||
* The names of the fields are not available.
 | 
			
		||||
* Enum names are not available, you'll have to use the values they are defined
 | 
			
		||||
  with.
 | 
			
		||||
* Default values are not available.
 | 
			
		||||
* Field types have to be hardcoded. The library does not know which types to
 | 
			
		||||
  expect, so the user of the library has to supply the right types. Some checks
 | 
			
		||||
  are made using `assert()`, but mostly the user has to take care of that.
 | 
			
		||||
 | 
			
		||||
The library will make sure not to overrun the buffer it was given, but
 | 
			
		||||
basically all other checks have to be made in user code!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
You have to have a working knowledge of how
 | 
			
		||||
[protocol buffer encoding works](https://developers.google.com/protocol-buffers/docs/encoding).
 | 
			
		||||
 | 
			
		||||
* Read the [tutorial](doc/tutorial.md) for an introduction on how to use
 | 
			
		||||
  Protozero.
 | 
			
		||||
* Some advanced topics are described in an [extra document](doc/advanced.md).
 | 
			
		||||
* There is a table of all types and functions in the
 | 
			
		||||
  [cheat sheet](doc/cheatsheet.md).
 | 
			
		||||
* 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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Endianness
 | 
			
		||||
 | 
			
		||||
Protozero uses a very simplistic test to check the byte order of the system it
 | 
			
		||||
compiles on. If this check is wrong, you'll get test failures. If this is the
 | 
			
		||||
case, please [open an issue](https://github.com/mapbox/protozero/issues) and
 | 
			
		||||
tell us about your system.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Building tests
 | 
			
		||||
 | 
			
		||||
Extensive tests are included. Build them using CMake:
 | 
			
		||||
 | 
			
		||||
    mkdir build
 | 
			
		||||
    cd build
 | 
			
		||||
    cmake ..
 | 
			
		||||
    make
 | 
			
		||||
 | 
			
		||||
Call `ctest` to run the tests.
 | 
			
		||||
 | 
			
		||||
The unit and reader tests are always build, the writer tests are only build if
 | 
			
		||||
the Google Protobuf library is found when running CMake.
 | 
			
		||||
 | 
			
		||||
See `test/README.md` for more details about the test.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Coverage report
 | 
			
		||||
 | 
			
		||||
To get a coverage report set `CXXFLAGS` and `LDFLAGS` before calling CMake:
 | 
			
		||||
 | 
			
		||||
    CXXFLAGS="--coverage" LDFLAGS="--coverage" cmake ..
 | 
			
		||||
 | 
			
		||||
Then call `make` as usual and run the tests using `ctest`.
 | 
			
		||||
 | 
			
		||||
If you are using `g++` use `gcov` to generate a report (results are in `*.gcov`
 | 
			
		||||
files):
 | 
			
		||||
 | 
			
		||||
    gcov -lp $(find test/ -name '*.o')
 | 
			
		||||
 | 
			
		||||
If you are using `clang++` use `llvm-cov` instead:
 | 
			
		||||
 | 
			
		||||
    llvm-cov gcov -lp $(find test/ -name '*.o')
 | 
			
		||||
 | 
			
		||||
If you are using `g++` you can use `gcovr` to generate nice HTML output:
 | 
			
		||||
 | 
			
		||||
    mkdir -p coverage
 | 
			
		||||
    gcovr . -r SRCDIR --html --html-details -o coverage/index.html
 | 
			
		||||
 | 
			
		||||
Open `coverage/index.html` in your browser to see the report.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Clang-tidy
 | 
			
		||||
 | 
			
		||||
After the CMake step, run
 | 
			
		||||
 | 
			
		||||
    make clang-tidy
 | 
			
		||||
 | 
			
		||||
to check the code with [clang-tidy](https://clang.llvm.org/extra/clang-tidy/).
 | 
			
		||||
You might have to set `CLANG_TIDY` in CMake config.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Cppcheck
 | 
			
		||||
 | 
			
		||||
For extra checks with [Cppcheck](http://cppcheck.sourceforge.net/) you can,
 | 
			
		||||
after the CMake step, call
 | 
			
		||||
 | 
			
		||||
    make cppcheck
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
After the CMake step, call `make install` to install the include files in
 | 
			
		||||
`/usr/local/include/protozero`.
 | 
			
		||||
 | 
			
		||||
If you are using CMake to build your own software, you can copy the file
 | 
			
		||||
`cmake/FindProtozero.cmake` and use it in your build. See the file for
 | 
			
		||||
details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Who is using Protozero?
 | 
			
		||||
 | 
			
		||||
* [Carmen](https://github.com/mapbox/carmen-cache)
 | 
			
		||||
* [Libosmium](https://github.com/osmcode/libosmium)
 | 
			
		||||
* [Mapbox GL Native](https://github.com/mapbox/mapbox-gl-native)
 | 
			
		||||
* [Mapbox Vector Tile library](https://github.com/mapbox/vector-tile)
 | 
			
		||||
* [Mapnik](https://github.com/mapbox/mapnik-vector-tile)
 | 
			
		||||
* [OSRM](https://github.com/Project-OSRM/osrm-backend)
 | 
			
		||||
* [Tippecanoe](https://github.com/mapbox/tippecanoe)
 | 
			
		||||
* [Vtzero](https://github.com/mapbox/vtzero)
 | 
			
		||||
 | 
			
		||||
Are you using Protozero? Tell us! Send a pull request with changes to this
 | 
			
		||||
README.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										96
									
								
								third_party/protozero/UPGRADING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								third_party/protozero/UPGRADING.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
			
		||||
 | 
			
		||||
# Upgrading
 | 
			
		||||
 | 
			
		||||
This file contains instructions for users of Protozero who are upgrading from
 | 
			
		||||
one version to another.
 | 
			
		||||
 | 
			
		||||
You do not need to change anything if only the minor version changes, but it
 | 
			
		||||
is better to keep up with changes if you can. The switch to the next major
 | 
			
		||||
version will be easier then. And you might get some more convenient usage.
 | 
			
		||||
 | 
			
		||||
To help you with upgrading to new versions, you can define the C++ preprocessor
 | 
			
		||||
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.5* to *v1.6.0*
 | 
			
		||||
 | 
			
		||||
* The `data_view` class moved from `types.hpp` into its own header file
 | 
			
		||||
  `data_view.hpp`. Most people should not include those headers directly,
 | 
			
		||||
  but if you do, you might have to change your includes.
 | 
			
		||||
* There are two new exceptions `invalid_tag_exception` and
 | 
			
		||||
  `invalid_length_exception` which cover cases that were only checked by
 | 
			
		||||
  `assert` before this version. If you catch specific exceptions in your code
 | 
			
		||||
  you might have to amend it. But just catching `protozero::exception` is
 | 
			
		||||
  usually fine for most code (if you catch exceptions at all).
 | 
			
		||||
* The `pbf_reader` constructor taking a `std::pair` is now deprecated. If you
 | 
			
		||||
  are compiling with `PROTOZERO_STRICT_API` it is not available any more. Use
 | 
			
		||||
  one of the other constructors instead.
 | 
			
		||||
 | 
			
		||||
## Upgrading from *v1.4.5* to *v1.5.0*
 | 
			
		||||
 | 
			
		||||
* New functions for checking tag and type at the same time to make your
 | 
			
		||||
  program more robust. Read the section "Repeated fields in messages" in
 | 
			
		||||
  the new [Advanced Topics documentation](doc/advanced.md).
 | 
			
		||||
 | 
			
		||||
## Upgrading from *v1.4.4* to *v1.4.5*
 | 
			
		||||
 | 
			
		||||
* The macro `PROTOZERO_DO_NOT_USE_BARE_POINTER` is not used any more. If you
 | 
			
		||||
  have been setting this, remove it.
 | 
			
		||||
 | 
			
		||||
## Upgrading from *v1.4.0* to *v1.4.1*
 | 
			
		||||
 | 
			
		||||
* You can now do `require('protozero')` in nodejs to print the path
 | 
			
		||||
  to the include paths for the protozero headers.
 | 
			
		||||
 | 
			
		||||
## Upgrading from *v1.3.0* to *v1.4.0*
 | 
			
		||||
 | 
			
		||||
* Functions in `pbf_reader` (and the derived `pbf_message`) called
 | 
			
		||||
  `get_packed_*()` now return an `iterator_range` instead of a `std::pair`.
 | 
			
		||||
  The new class is derived from `std::pair`, so changes are usually not
 | 
			
		||||
  strictly necessary. For future compatibility, you should change all
 | 
			
		||||
  attribute accesses on the returned objects from `first` and `second` to
 | 
			
		||||
  `begin()` and `end()`, respectively. So change something like this:
 | 
			
		||||
 | 
			
		||||
      auto x = message.get_packed_int32();
 | 
			
		||||
      for (auto it = x.first; it != x.second; ++it) {
 | 
			
		||||
          ....
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  to:
 | 
			
		||||
 | 
			
		||||
      auto x = message.get_packed_int32();
 | 
			
		||||
      for (auto it = x.begin(); it != x.end(); ++it) {
 | 
			
		||||
          ....
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  or even better use the range-based for loop:
 | 
			
		||||
 | 
			
		||||
      auto x = message.get_packed_int32();
 | 
			
		||||
      for (auto val : x) {
 | 
			
		||||
          ....
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
  Ranges can also be used in this way. This will change the range in-place:
 | 
			
		||||
 | 
			
		||||
      auto range = message.get_packed_int32();
 | 
			
		||||
      while (!range.empty()) {
 | 
			
		||||
          auto value = range.front();
 | 
			
		||||
          range.drop_front();
 | 
			
		||||
          ....
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
* The class `pbf_reader` has a new method `get_view()` returning an object
 | 
			
		||||
  of the new `protozero::data_view` class. The `data_view` only has minimal
 | 
			
		||||
  functionality, but what it has is compatible to the `std::string_view` class
 | 
			
		||||
  which will be coming in C++17. The view autoconverts to a `std::string` if
 | 
			
		||||
  needed. Use `get_view()` instead of `get_data()` giving you a more intuitive
 | 
			
		||||
  interface (call `data()` and `size()` on the view instead of using `first`
 | 
			
		||||
  and `second` on the `std::pair` returned by `get_data()`).
 | 
			
		||||
 | 
			
		||||
  You can set the macro `PROTOZERO_USE_VIEW` (before including `types.hpp`) to
 | 
			
		||||
  the name of any class that behaves like `protozero::data_view` and
 | 
			
		||||
  `data_view` will be an alias to that class instead of the implementation
 | 
			
		||||
  from protozero. This way you can use the C++17 `string_view` or a similar
 | 
			
		||||
  class if it is already available on your system.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										57
									
								
								third_party/protozero/appveyor.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								third_party/protozero/appveyor.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Configuration for continuous integration service at appveyor.com
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
platform: x64
 | 
			
		||||
 | 
			
		||||
image: Visual Studio 2017
 | 
			
		||||
 | 
			
		||||
clone_depth: 1
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  matrix:
 | 
			
		||||
  - config: MSYS2
 | 
			
		||||
    autocrlf: true
 | 
			
		||||
  - config: Debug
 | 
			
		||||
    autocrlf: true
 | 
			
		||||
  - config: RelWithDebInfo
 | 
			
		||||
    autocrlf: true
 | 
			
		||||
  - config: Debug
 | 
			
		||||
    autocrlf: false
 | 
			
		||||
  - config: RelWithDebInfo
 | 
			
		||||
    autocrlf: false
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
init:
 | 
			
		||||
  - git config --global core.autocrlf %autocrlf%
 | 
			
		||||
  - git config --get core.autocrlf
 | 
			
		||||
 | 
			
		||||
# The option --ask=20 is a workaround for a problem with the MSYS2 update
 | 
			
		||||
# process. Without it the following error is printed and the appveyor script
 | 
			
		||||
# 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
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
build_script:
 | 
			
		||||
  - if [%config%]==[MSYS2] (
 | 
			
		||||
        build-msys2.bat
 | 
			
		||||
    ) else (
 | 
			
		||||
        build-appveyor.bat
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
# 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"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										13
									
								
								third_party/protozero/bench/data/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								third_party/protozero/bench/data/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
mapbox-streets-v6/14/8714/8017.vector.pbf
 | 
			
		||||
 | 
			
		||||
 - http://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/
 | 
			
		||||
 | 
			
		||||
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/
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/bench/data/enf-14-4824-6157.vector.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/bench/data/enf-14-4824-6157.vector.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/bench/data/mapbox-streets-v6-14-8714-8017.vector.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/bench/data/mapbox-streets-v6-14-8714-8017.vector.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										65
									
								
								third_party/protozero/build-appveyor.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								third_party/protozero/build-appveyor.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
@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%
 | 
			
		||||
							
								
								
									
										29
									
								
								third_party/protozero/build-local.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								third_party/protozero/build-local.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
@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%
 | 
			
		||||
							
								
								
									
										18
									
								
								third_party/protozero/build-msys2.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								third_party/protozero/build-msys2.bat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								third_party/protozero/cmake/FindProtozero.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								third_party/protozero/cmake/FindProtozero.cmake
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  FindProtozero.cmake
 | 
			
		||||
#
 | 
			
		||||
#  Find the protozero headers.
 | 
			
		||||
#
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Usage:
 | 
			
		||||
#
 | 
			
		||||
#    Copy this file somewhere into your project directory, where cmake can
 | 
			
		||||
#    find it. Usually this will be a directory called "cmake" which you can
 | 
			
		||||
#    add to the CMake module search path with the following line in your
 | 
			
		||||
#    CMakeLists.txt:
 | 
			
		||||
#
 | 
			
		||||
#      list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
 | 
			
		||||
#
 | 
			
		||||
#    Then add the following in your CMakeLists.txt:
 | 
			
		||||
#
 | 
			
		||||
#      find_package(Protozero [version] [REQUIRED])
 | 
			
		||||
#      include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
 | 
			
		||||
#
 | 
			
		||||
#    The version number is optional. If it is not set, any version of
 | 
			
		||||
#    protozero will do.
 | 
			
		||||
#
 | 
			
		||||
#      if(NOT PROTOZERO_FOUND)
 | 
			
		||||
#          message(WARNING "Protozero not found!\n")
 | 
			
		||||
#      endif()
 | 
			
		||||
#
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  Variables:
 | 
			
		||||
#
 | 
			
		||||
#    PROTOZERO_FOUND        - True if Protozero was found.
 | 
			
		||||
#    PROTOZERO_INCLUDE_DIR  - Where to find include files.
 | 
			
		||||
#
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
# find include path
 | 
			
		||||
find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp
 | 
			
		||||
    PATH_SUFFIXES include
 | 
			
		||||
    PATHS ${CMAKE_SOURCE_DIR}/../protozero
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Check version number
 | 
			
		||||
if(Protozero_FIND_VERSION)
 | 
			
		||||
    file(STRINGS "${PROTOZERO_INCLUDE_DIR}/protozero/version.hpp" _version_define REGEX "#define PROTOZERO_VERSION_STRING")
 | 
			
		||||
    if("${_version_define}" MATCHES "#define PROTOZERO_VERSION_STRING \"([0-9.]+)\"")
 | 
			
		||||
        set(_version "${CMAKE_MATCH_1}")
 | 
			
		||||
    else()
 | 
			
		||||
        set(_version "unknown")
 | 
			
		||||
    endif()
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
#set(PROTOZERO_INCLUDE_DIRS "${PROTOZERO_INCLUDE_DIR}")
 | 
			
		||||
 | 
			
		||||
include(FindPackageHandleStandardArgs)
 | 
			
		||||
find_package_handle_standard_args(Protozero
 | 
			
		||||
                                  REQUIRED_VARS PROTOZERO_INCLUDE_DIR
 | 
			
		||||
                                  VERSION_VAR _version)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#----------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										37
									
								
								third_party/protozero/doc/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								third_party/protozero/doc/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  CMake Config
 | 
			
		||||
#
 | 
			
		||||
#  protozero documentation
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
message(STATUS "Configuring documentation")
 | 
			
		||||
 | 
			
		||||
message(STATUS "Looking for doxygen")
 | 
			
		||||
find_package(Doxygen)
 | 
			
		||||
 | 
			
		||||
if(DOXYGEN_FOUND)
 | 
			
		||||
    message(STATUS "Looking for doxygen - found")
 | 
			
		||||
    configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
 | 
			
		||||
 | 
			
		||||
    file(GLOB HEADER_FILES "${CMAKE_SOURCE_DIR}/include/protozero/*.hpp")
 | 
			
		||||
    add_custom_command(OUTPUT html/index.html
 | 
			
		||||
        COMMAND ${DOXYGEN_EXECUTABLE}
 | 
			
		||||
        ARGS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
 | 
			
		||||
        DEPENDS Doxyfile.in advanced.md cheatsheet.md tutorial.md
 | 
			
		||||
                ${HEADER_FILES}
 | 
			
		||||
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
 | 
			
		||||
        COMMENT "Generating API documentation with Doxygen" VERBATIM)
 | 
			
		||||
    add_custom_target(doc ALL
 | 
			
		||||
                      DEPENDS html/index.html)
 | 
			
		||||
else()
 | 
			
		||||
    message(STATUS "Looking for doxygen - not found")
 | 
			
		||||
    message(STATUS "  Disabled making of documentation.")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
message(STATUS "Configuring documentation - done")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										2355
									
								
								third_party/protozero/doc/Doxyfile.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2355
									
								
								third_party/protozero/doc/Doxyfile.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										271
									
								
								third_party/protozero/doc/advanced.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								third_party/protozero/doc/advanced.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,271 @@
 | 
			
		||||
 | 
			
		||||
# Protozero Advanced Topics
 | 
			
		||||
 | 
			
		||||
This documentation contains some mixed advanced topics for Protozero users.
 | 
			
		||||
Read the [tutorial](tutorial.md) first if you are new to Protozero.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Limitations of Protozero
 | 
			
		||||
 | 
			
		||||
* A protobuf message has to fit into memory completely, otherwise it can not
 | 
			
		||||
  be parsed with this library. There is no streaming support.
 | 
			
		||||
* The length of a string, bytes, or submessage can't be more than 2^31-1.
 | 
			
		||||
* There is no specific support for maps but they can be used as described in
 | 
			
		||||
  the "Backwards compatibility" section of
 | 
			
		||||
  https://developers.google.com/protocol-buffers/docs/proto3#maps.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Checking the Protozero version number
 | 
			
		||||
 | 
			
		||||
If `protozero/version.hpp` is included, the following macros are set:
 | 
			
		||||
 | 
			
		||||
| Macro                      | Example | Description                                    |
 | 
			
		||||
| -------------------------- | ------- | ---------------------------------------------- |
 | 
			
		||||
| `PROTOZERO_VERSION_MAJOR`  | 1       | Major version number                           |
 | 
			
		||||
| `PROTOZERO_VERSION_MINOR`  | 3       | Minor version number                           |
 | 
			
		||||
| `PROTOZERO_VERSION_PATCH`  | 2       | Patch number                                   |
 | 
			
		||||
| `PROTOZERO_VERSION_CODE`   | 10302   | Version (major * 10,000 + minor * 100 + patch) |
 | 
			
		||||
| `PROTOZERO_VERSION_STRING` | "1.3.2" | Version string                                 |
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Changing Protozero behaviour with macros
 | 
			
		||||
 | 
			
		||||
The behaviour of Protozero can be changed by defining the following macros.
 | 
			
		||||
They have to be set before including any of the Protozero headers.
 | 
			
		||||
 | 
			
		||||
### `PROTOZERO_STRICT_API`
 | 
			
		||||
 | 
			
		||||
If this is set, you will get some extra warnings or errors during compilation
 | 
			
		||||
if you are using an old (deprecated) interface to Protozero. Enable this if
 | 
			
		||||
you want to make sure your code will work with future versions of Protozero.
 | 
			
		||||
 | 
			
		||||
### `PROTOZERO_USE_VIEW`
 | 
			
		||||
 | 
			
		||||
Protozero uses the class `protozero::data_view` as the return type of the
 | 
			
		||||
`pbf_reader::get_view()` method and a few other functions take a
 | 
			
		||||
`protozero::data_view` as parameter.
 | 
			
		||||
 | 
			
		||||
If `PROTOZERO_USE_VIEW` is unset, `protozero::data_view` is Protozero's own
 | 
			
		||||
implementation of a *string view* class.
 | 
			
		||||
 | 
			
		||||
Set this macro if you want to use a different implementation such as the C++17
 | 
			
		||||
`std::string_view` class. In this case `protozero::data_view` will simply be
 | 
			
		||||
an alias to the class you specify.
 | 
			
		||||
 | 
			
		||||
    #define PROTOZERO_USE_VIEW std::string_view
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Repeated fields in messages
 | 
			
		||||
 | 
			
		||||
The Google Protobuf spec documents that a non-repeated field can actually
 | 
			
		||||
appear several times in a message and the implementation is required to return
 | 
			
		||||
the value of the last version of that field in this case. `pbf_reader.hpp` does
 | 
			
		||||
not enforce this. If this feature is needed in your case, you have to do this
 | 
			
		||||
yourself.
 | 
			
		||||
 | 
			
		||||
The [spec also
 | 
			
		||||
says](https://developers.google.com/protocol-buffers/docs/encoding#packed)
 | 
			
		||||
that you must be able to read a packed repeated field where a not-packed
 | 
			
		||||
repeated field is expected and vice versa. Also there can be several (packed or
 | 
			
		||||
not-packed) repeated fields with the same tag and their contents must be
 | 
			
		||||
concatenated. It is your responsibility to do this, Protozero doesn't do that
 | 
			
		||||
for you.
 | 
			
		||||
 | 
			
		||||
### Using `tag_and_type()`
 | 
			
		||||
 | 
			
		||||
The `tag_and_type()` free function and the method of the same name on the
 | 
			
		||||
`pbf_reader` and `pbf_message` classes can be used to access both packed and
 | 
			
		||||
unpacked repeated fields. (It can also be used to check that you have the
 | 
			
		||||
right type of encoding for other fields.)
 | 
			
		||||
 | 
			
		||||
Here is the outline:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
enum class ExampleMsg : protozero::pbf_tag_type {
 | 
			
		||||
    repeated_uint32_x = 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::string data = ...
 | 
			
		||||
pbf_message<ExampleMsg> message{data};
 | 
			
		||||
while (message.next()) {
 | 
			
		||||
    switch (message.tag_and_type()) {
 | 
			
		||||
        case tag_and_type(ExampleMsg::repeated_uint32_x, pbf_wire_type::length_delimited): {
 | 
			
		||||
                auto xit = message.get_packed_uint32();
 | 
			
		||||
                ... // handle the repeated field when it is packed
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case tag_and_type(ExampleMsg::repeated_uint32_x, pbf_wire_type::varint): {
 | 
			
		||||
                auto x = message.get_uint32();
 | 
			
		||||
                ... // handle the repeated field when it is not packed
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            message.skip();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
All this works on `pbf_reader` in the same way as with `pbf_message` with the
 | 
			
		||||
usual difference that `pbf_reader` takes a numeric field tag and `pbf_message`
 | 
			
		||||
an enum field.
 | 
			
		||||
 | 
			
		||||
If you only want to check for one specific tag and type you can use the
 | 
			
		||||
two-argument version of `pbf_reader::next()`. In this case `17` is the field
 | 
			
		||||
tag we are looking for:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data = ...
 | 
			
		||||
pbf_reader message{data};
 | 
			
		||||
while (message.next(17, pbf_wire_type::varint)) {
 | 
			
		||||
    auto foo = message.get_int32();
 | 
			
		||||
    ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
See the test under `test/t/tag_and_type/` for a complete example.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Reserving memory when writing messages
 | 
			
		||||
 | 
			
		||||
If you know beforehand how large a message will become or can take an educated
 | 
			
		||||
guess, you can call the usual `std::string::reserve()` on the underlying string
 | 
			
		||||
before you give it to an `pbf_writer` or `pbf_builder` object.
 | 
			
		||||
 | 
			
		||||
Or you can (at any time) call `reserve()` on the `pbf_writer` or `pbf_builder`.
 | 
			
		||||
This will reserve the given amount of bytes *in addition to whatever is already
 | 
			
		||||
in that message*. (Note that this behaviour is different then what `reserve()`
 | 
			
		||||
does on `std::string` or `std::vector`.)
 | 
			
		||||
 | 
			
		||||
In the general case it is not easy to figure out how much memory you will need
 | 
			
		||||
because of the varint packing of integers. But sometimes you can make at least
 | 
			
		||||
a rough estimate. Still, you should probably only use this facility if you have
 | 
			
		||||
benchmarks proving that it actually makes your program faster.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Using the low-level varint and zigzag encoding and decoding functions
 | 
			
		||||
 | 
			
		||||
Protozero gives you access to the low-level functions for encoding and
 | 
			
		||||
decoding varint and zigzag integer encodings, because these functions can
 | 
			
		||||
sometimes be useful outside the Protocol Buffer context.
 | 
			
		||||
 | 
			
		||||
### Using low-level functions
 | 
			
		||||
 | 
			
		||||
To use the low-level functions, add this include to your C++ program:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/varint.hpp>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Functions
 | 
			
		||||
 | 
			
		||||
The following functions are then available:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
decode_varint()
 | 
			
		||||
write_varint()
 | 
			
		||||
encode_zigzag32()
 | 
			
		||||
encode_zigzag64()
 | 
			
		||||
decode_zigzag32()
 | 
			
		||||
decode_zigzag64()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
See the reference documentation created by `make doc` for details.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Vectored input for length-delimited fields
 | 
			
		||||
 | 
			
		||||
Length-delimited fields (like string fields, byte fields and messages) are
 | 
			
		||||
usually set by calling `add_string()`, `add_message()`, etc. These functions
 | 
			
		||||
have several forms, but they basically all take a *tag*, a *size*, and a
 | 
			
		||||
*pointer to the data*. They write the length of the data into the message
 | 
			
		||||
and then copy the data over.
 | 
			
		||||
 | 
			
		||||
Sometimes you have the data not in one place, but spread over several
 | 
			
		||||
buffers. In this case you have to consolidate those buffers first, which needs
 | 
			
		||||
an extra copy. Say you have two very long strings that should be concatenated
 | 
			
		||||
into a message:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string a{"very long string..."};
 | 
			
		||||
std::string b{"another very long string..."};
 | 
			
		||||
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer writer{data};
 | 
			
		||||
 | 
			
		||||
a.append(b); // expensive extra copy
 | 
			
		||||
 | 
			
		||||
writer.add_string(1, a);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To avoid this, the function `add_bytes_vectored()` can be used which allows
 | 
			
		||||
vectored (or scatter/gather) input like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string a{"very long string..."};
 | 
			
		||||
std::string b{"another very long string..."};
 | 
			
		||||
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer writer{data};
 | 
			
		||||
 | 
			
		||||
writer.add_bytes_vectored(1, a, b);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
`add_bytes_vectored()` will add up the sizes of all its arguments and copy over
 | 
			
		||||
all the data only once.
 | 
			
		||||
 | 
			
		||||
The function takes any number of arguments. The arguments must be of a type
 | 
			
		||||
supporting the `data()` and `size()` methods like `protozero::data_view()`,
 | 
			
		||||
`std::string` or the C++17 `std::string_view`.
 | 
			
		||||
 | 
			
		||||
Note that there is only one version of the function which can be used for any
 | 
			
		||||
length-delimited field including strings, bytes, messages and repeated packed
 | 
			
		||||
fields.
 | 
			
		||||
 | 
			
		||||
The function is also available in the `pbf_builder` class.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Internal handling of varints
 | 
			
		||||
 | 
			
		||||
When varints are decoded they are always decoded as 64bit unsigned integers and
 | 
			
		||||
after that casted to the type you are requesting (using `static_cast`). This
 | 
			
		||||
means that if the protocol buffer message was created with a different integer
 | 
			
		||||
type than what you are reading it with, you might get wrong results without any
 | 
			
		||||
warning or error. This is the same behaviour as the Google Protocol Buffers
 | 
			
		||||
library has.
 | 
			
		||||
 | 
			
		||||
In normal use, this should never matter, because presumably you are using the
 | 
			
		||||
same types to write that data as you are using to read it later. It can happen
 | 
			
		||||
if the data is corrupted intentionally or unintentionally in some way. But
 | 
			
		||||
this can't be used to feed you any data that it wasn't possible to feed you
 | 
			
		||||
without this behaviour, so it doesn't open up any potential problems. You
 | 
			
		||||
always have to check anyway that the integers are in the range you expected
 | 
			
		||||
them to be in if the expected range is different than the range of the integer
 | 
			
		||||
type. This is especially true for enums which protozero will return as
 | 
			
		||||
`int32_t`.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## How many items are there in a repeated packed field?
 | 
			
		||||
 | 
			
		||||
Sometimes it is useful to know how many values there are in a repeated packed
 | 
			
		||||
field. For instance when you want to reserve space in a `std::vector`.
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
protozero::pbf_reader message{...};
 | 
			
		||||
message.next(...);
 | 
			
		||||
const auto range = message.get_packed_sint32();
 | 
			
		||||
 | 
			
		||||
std::vector<int> myvalues;
 | 
			
		||||
myvalues.reserve(range.size());
 | 
			
		||||
 | 
			
		||||
for (auto value : range) {
 | 
			
		||||
    myvalues.push_back(value);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
It depends on the type of range how expensive the `size()` call is. For ranges
 | 
			
		||||
derived from packed repeated fixed sized values the effort will be constant,
 | 
			
		||||
for ranges derived from packed repeated varints, the effort will be linear, but
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								third_party/protozero/doc/cheatsheet.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								third_party/protozero/doc/cheatsheet.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
			
		||||
 | 
			
		||||
# Protozero Cheat Sheet
 | 
			
		||||
 | 
			
		||||
See also this
 | 
			
		||||
[handy table](https://developers.google.com/protocol-buffers/docs/proto#scalar)
 | 
			
		||||
from the Google Protocol Buffers documentation.
 | 
			
		||||
 | 
			
		||||
## Scalar types
 | 
			
		||||
 | 
			
		||||
| PBF Type | Underlying Storage | C++ Type      | Getter           | Notes |
 | 
			
		||||
| -------- | ------------------ | ------------- | ---------------- | ----- |
 | 
			
		||||
| int32    | varint             | `int32_t`     | `get_int32()`    |       |
 | 
			
		||||
| sint32   | varint (zigzag)    | `int32_t`     | `get_sint32()`   |       |
 | 
			
		||||
| uint32   | varint             | `uint32_t`    | `get_uint32()`   |       |
 | 
			
		||||
| int64    | varint             | `int64_t`     | `get_int64()`    |       |
 | 
			
		||||
| sint64   | varint (zigzag)    | `int64_t`     | `get_sint64()`   |       |
 | 
			
		||||
| uint64   | varint             | `uint64_t`    | `get_uint64()`   |       |
 | 
			
		||||
| bool     | varint             | `bool`        | `get_bool()`     |       |
 | 
			
		||||
| enum     | varint             | `int32_t`     | `get_enum()`     |       |
 | 
			
		||||
| fixed32  | 32bit fixed        | `uint32_t`    | `get_fixed32()`  |       |
 | 
			
		||||
| sfixed32 | 32bit fixed        | `int32_t`     | `get_sfixed32()` |       |
 | 
			
		||||
| fixed64  | 64bit fixed        | `uint64_t`    | `get_fixed64()`  |       |
 | 
			
		||||
| sfixed64 | 64bit fixed        | `int64_t`     | `get_sfixed64()` |       |
 | 
			
		||||
| float    | 32bit fixed        | `float`       | `get_float()`    |       |
 | 
			
		||||
| double   | 64bit fixed        | `double`      | `get_double()`   |       |
 | 
			
		||||
| string   | length-delimited   | `data_view`   | `get_view()`     | (1)   |
 | 
			
		||||
| string   | length-delimited   | pair          | `get_data()`     | (2)   |
 | 
			
		||||
| string   | length-delimited   | `std::string` | `get_string()`   |       |
 | 
			
		||||
| bytes    | length-delimited   | `data_view`   | `get_view()`     | (1)   |
 | 
			
		||||
| bytes    | length-delimited   | pair          | `get_data()`     | (2)   |
 | 
			
		||||
| bytes    | length-delimited   | `std::string` | `get_bytes()`    |       |
 | 
			
		||||
| message  | length-delimited   | `data_view`   | `get_view()`     | (1)   |
 | 
			
		||||
| message  | length-delimited   | pair          | `get_data()`     | (2)   |
 | 
			
		||||
| message  | length-delimited   | `pbf_reader`  | `get_message()`  |       |
 | 
			
		||||
 | 
			
		||||
### Notes:
 | 
			
		||||
 | 
			
		||||
* (1) preferred form, returns `protozero::data_view` which is convertible to
 | 
			
		||||
  `std::string` if needed.
 | 
			
		||||
* (2) deprecated form, returns `std::pair<const char*, pbf_length_type>`,
 | 
			
		||||
  use `get_view()` instead. This form is only available if
 | 
			
		||||
  `PROTOZERO_STRICT_API` is not defined.
 | 
			
		||||
* The setter function of `pbf_writer` is always `add_` + the PBF type. Several
 | 
			
		||||
  overloads are available.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Packed repeated fields
 | 
			
		||||
 | 
			
		||||
| PBF Type | Getter                  |
 | 
			
		||||
| -------- | ----------------------- |
 | 
			
		||||
| int32    | `get_packed_int32()`    |
 | 
			
		||||
| sint32   | `get_packed_sint32()`   |
 | 
			
		||||
| uint32   | `get_packed_uint32()`   |
 | 
			
		||||
| int64    | `get_packed_int64()`    |
 | 
			
		||||
| sint64   | `get_packed_sint64()`   |
 | 
			
		||||
| uint64   | `get_packed_uint64()`   |
 | 
			
		||||
| bool     | `get_packed_bool()`     |
 | 
			
		||||
| enum     | `get_packed_enum()`     |
 | 
			
		||||
| fixed32  | `get_packed_fixed32()`  |
 | 
			
		||||
| sfixed32 | `get_packed_sfixed32()` |
 | 
			
		||||
| fixed64  | `get_packed_fixed64()`  |
 | 
			
		||||
| sfixed64 | `get_packed_sfixed64()` |
 | 
			
		||||
| float    | `get_packed_float()`    |
 | 
			
		||||
| double   | `get_packed_double()`   |
 | 
			
		||||
 | 
			
		||||
Packed repeated fields for string, bytes, and message types are not possible.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										626
									
								
								third_party/protozero/doc/tutorial.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										626
									
								
								third_party/protozero/doc/tutorial.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,626 @@
 | 
			
		||||
 | 
			
		||||
# Protozero Tutorial
 | 
			
		||||
 | 
			
		||||
## Getting to know Protocol Buffers
 | 
			
		||||
 | 
			
		||||
Protozero is a very low level library. You really have to know some of the
 | 
			
		||||
insides of Protocol Buffers to work with it!
 | 
			
		||||
 | 
			
		||||
So before reading any further in this document, read the following from the
 | 
			
		||||
Protocol Buffer documentation:
 | 
			
		||||
 | 
			
		||||
* [Developer Guide - Overview](https://developers.google.com/protocol-buffers/docs/overview)
 | 
			
		||||
* [Language Guide](https://developers.google.com/protocol-buffers/docs/proto)
 | 
			
		||||
* [Encoding](https://developers.google.com/protocol-buffers/docs/encoding)
 | 
			
		||||
 | 
			
		||||
Make sure you understand the basic types of values supported by Protocol
 | 
			
		||||
Buffers. Refer to this
 | 
			
		||||
[handy table](https://developers.google.com/protocol-buffers/docs/proto#scalar)
 | 
			
		||||
and [the cheat sheet](cheatsheet.md) if you are getting lost.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Prerequisites
 | 
			
		||||
 | 
			
		||||
You need a C++11-capable compiler for Protozero to work. Copy the files in the
 | 
			
		||||
`include/protozero` directory somewhere where your build system can find them.
 | 
			
		||||
Keep the `protozero` directory and include the files in the form
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/FILENAME.hpp>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Parsing protobuf-encoded messages
 | 
			
		||||
 | 
			
		||||
### Using `pbf_reader`
 | 
			
		||||
 | 
			
		||||
To use the `pbf_reader` class, add this include to your C++ program:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/pbf_reader.hpp>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `pbf_reader` class contains asserts that will detect some programming
 | 
			
		||||
errors. We encourage you to compile with asserts enabled in your debug builds.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### An introductory example
 | 
			
		||||
 | 
			
		||||
Lets say you have a protocol description in a `.proto` file like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
message Example1 {
 | 
			
		||||
    required uint32 x  =  1;
 | 
			
		||||
    optional string s  =  2;
 | 
			
		||||
    repeated fixed64 r = 17;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To read messages created according to that description, you will have code that
 | 
			
		||||
looks somewhat like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/pbf_reader.hpp>
 | 
			
		||||
 | 
			
		||||
// get data from somewhere into the input string
 | 
			
		||||
std::string input = get_input_data();
 | 
			
		||||
 | 
			
		||||
// initialize pbf message with this data
 | 
			
		||||
protozero::pbf_reader message{input};
 | 
			
		||||
 | 
			
		||||
// iterate over fields in the message
 | 
			
		||||
while (message.next()) {
 | 
			
		||||
 | 
			
		||||
    // switch depending on the field tag (the field name is not available)
 | 
			
		||||
    switch (message.tag()) {
 | 
			
		||||
        case 1:
 | 
			
		||||
            // get data for tag 1 (in this case an uint32)
 | 
			
		||||
            auto x = message.get_uint32();
 | 
			
		||||
            break;
 | 
			
		||||
        case 2:
 | 
			
		||||
            // get data for tag 2 (in this case a string)
 | 
			
		||||
            std::string s = message.get_string();
 | 
			
		||||
            break;
 | 
			
		||||
        case 17:
 | 
			
		||||
            // ignore data for tag 17
 | 
			
		||||
            message.skip();
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            // ignore data for unknown tags to allow for future extensions
 | 
			
		||||
            message.skip();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You always have to call `next()` and then either one of the accessor functions
 | 
			
		||||
(like `get_uint32()` or `get_string()`) to get the field value or `skip()` to
 | 
			
		||||
ignore this field. Then call `next()` again, and so forth. Never call `next()`
 | 
			
		||||
twice in a row or any if the accessor or skip functions twice in a row.
 | 
			
		||||
 | 
			
		||||
Because the `pbf_reader` class doesn't know the `.proto` file it doesn't know
 | 
			
		||||
which field names or tags there are and it doesn't known the types of the
 | 
			
		||||
fields. You have to make sure to call the right `get_...()` function for each
 | 
			
		||||
tag. Some `assert()s` are done to check you are calling the right functions,
 | 
			
		||||
but not all errors can be detected.
 | 
			
		||||
 | 
			
		||||
Note that it doesn't matter whether a field is defined as `required`,
 | 
			
		||||
`optional`, or `repeated`. You always have to be prepared to get zero, one, or
 | 
			
		||||
more instances of a field and you always have to be prepared to get other
 | 
			
		||||
fields, too, unless you want your program to break if somebody adds a new
 | 
			
		||||
field.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### If you only need a single field
 | 
			
		||||
 | 
			
		||||
If, out of a protocol buffer message, you only need the value of a single
 | 
			
		||||
field, you can use the version of the `next()` function with a parameter:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
// same .proto file and initialization as above
 | 
			
		||||
 | 
			
		||||
// get all fields with tag 17, skip all others
 | 
			
		||||
while (message.next(17)) {
 | 
			
		||||
    auto r = message.get_fixed64();
 | 
			
		||||
    std::cout << r << "\n";
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Handling scalar fields
 | 
			
		||||
 | 
			
		||||
As you saw in the example, handling scalar field types is reasonably easy. You
 | 
			
		||||
just check the `.proto` file for the type of a field and call the corresponding
 | 
			
		||||
function called `get_` + _field type_.
 | 
			
		||||
 | 
			
		||||
For `string` and `bytes` types the internal handling is exactly the same, but
 | 
			
		||||
both `get_string()` and `get_bytes()` are provided to make the code
 | 
			
		||||
self-documenting. Both theses calls allocate and return a `std::string` which
 | 
			
		||||
can add some overhead. You can call the `get_view()` function instead which
 | 
			
		||||
returns a `data_view` containing a pointer into the data (access with `data()`)
 | 
			
		||||
and the length of the data (access with `size()`).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Handling repeated packed fields
 | 
			
		||||
 | 
			
		||||
Fields that are marked as `[packed=true]` in the `.proto` file are handled
 | 
			
		||||
somewhat differently. `get_packed_...()` functions returning an iterator range
 | 
			
		||||
are used to access the data.
 | 
			
		||||
 | 
			
		||||
So, for example, if you have a protocol description in a `.proto` file like
 | 
			
		||||
this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
message Example2 {
 | 
			
		||||
    repeated sint32 i = 1 [packed=true];
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You can get to the data like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
protozero::pbf_reader message{input.data(), input.size()};
 | 
			
		||||
 | 
			
		||||
// set current field
 | 
			
		||||
message.next(1);
 | 
			
		||||
 | 
			
		||||
// get an iterator range
 | 
			
		||||
auto pi = message.get_packed_sint32();
 | 
			
		||||
 | 
			
		||||
// iterate to get to all values
 | 
			
		||||
for (auto it = pi.begin(); it != pi.end(); ++it) {
 | 
			
		||||
    std::cout << *it << '\n';
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or, with a range-based for-loop:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
for (auto value : pi) {
 | 
			
		||||
    std::cout << v << '\n';
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
So you are getting a pair of normal forward iterators wrapped in an iterator
 | 
			
		||||
range object. The iterators can be used with any STL algorithms etc.
 | 
			
		||||
 | 
			
		||||
Note that the previous only applies to repeated **packed** fields, normal
 | 
			
		||||
repeated fields are handled in the usual way for scalar fields.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Handling embedded messages
 | 
			
		||||
 | 
			
		||||
Protocol Buffers can embed any message inside another message. To access an
 | 
			
		||||
embedded message use the `get_message()` function. So for this description:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
message Point {
 | 
			
		||||
    required double x = 1;
 | 
			
		||||
    required double y = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Example3 {
 | 
			
		||||
    repeated Point point = 10;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
you can parse with this code:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
protozero::pbf_reader message{input};
 | 
			
		||||
 | 
			
		||||
while (message.next(10)) {
 | 
			
		||||
    protozero::pbf_reader point = message.get_message();
 | 
			
		||||
    double x, y;
 | 
			
		||||
    while (point.next()) {
 | 
			
		||||
        switch (point.tag()) {
 | 
			
		||||
            case 1:
 | 
			
		||||
                x = point.get_double();
 | 
			
		||||
                break;
 | 
			
		||||
            case 2:
 | 
			
		||||
                y = point.get_double();
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                point.skip();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout << "x=" << x << " y=" << y << "\n";
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Handling enums
 | 
			
		||||
 | 
			
		||||
Enums are stored as varints and they can't be differentiated from them. Use
 | 
			
		||||
the `get_enum()` function to get the value of the enum, you have to translate
 | 
			
		||||
this into the symbolic name yourself. See the `enum` test case for an example.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Asserts and exceptions in the Protozero library
 | 
			
		||||
 | 
			
		||||
Protozero uses `assert()` liberally to help you find bugs in your own code when
 | 
			
		||||
compiled in debug mode (ie with `NDEBUG` not set). If such an assert "fires",
 | 
			
		||||
this is a very strong indication that there is a bug in your code somewhere.
 | 
			
		||||
 | 
			
		||||
(Protozero will disable those asserts and "convert" them into exception in its
 | 
			
		||||
own test code. This is done to make sure the asserts actually work as intended.
 | 
			
		||||
Your test code will not need this!)
 | 
			
		||||
 | 
			
		||||
Exceptions, on the other hand, are thrown by Protozero if some kind of data
 | 
			
		||||
corruption was detected while it is trying to parse the data. This could also
 | 
			
		||||
be an indicator for a bug in the user code, but because it can happen if the
 | 
			
		||||
data was (intentionally or not intentionally) been messed with, it is reported
 | 
			
		||||
to the user code using exceptions.
 | 
			
		||||
 | 
			
		||||
Most of the functions on the writer side can throw a `std::bad_alloc`
 | 
			
		||||
exception if there is no space to grow a buffer. Other than that no exceptions
 | 
			
		||||
can occur on the writer side.
 | 
			
		||||
 | 
			
		||||
All exceptions thrown by the reader side derive from `protozero::exception`.
 | 
			
		||||
 | 
			
		||||
Note that all exceptions can also happen if you are expecting a data field of
 | 
			
		||||
a certain type in your code but the field actually has a different type. In
 | 
			
		||||
that case the `pbf_reader` class might interpret the bytes in the buffer in
 | 
			
		||||
the wrong way and anything can happen.
 | 
			
		||||
 | 
			
		||||
#### `end_of_buffer_exception`
 | 
			
		||||
 | 
			
		||||
This will be thrown whenever any of the functions "runs out of input data".
 | 
			
		||||
It means you either have an incomplete message in your input or some other
 | 
			
		||||
data corruption has taken place.
 | 
			
		||||
 | 
			
		||||
#### `unknown_pbf_wire_type_exception`
 | 
			
		||||
 | 
			
		||||
This will be thrown if an unsupported wire type is encountered. Either your
 | 
			
		||||
input data is corrupted or it was written with an unsupported version of a
 | 
			
		||||
Protocol Buffers implementation.
 | 
			
		||||
 | 
			
		||||
#### `varint_too_long_exception`
 | 
			
		||||
 | 
			
		||||
This exception indicates an illegal encoding of a varint. It means your input
 | 
			
		||||
data is corrupted in some way.
 | 
			
		||||
 | 
			
		||||
#### `invalid_tag_exception`
 | 
			
		||||
 | 
			
		||||
This exception is thrown when a tag has an invalid value. Tags must be
 | 
			
		||||
unsigned integers between 1 and 2^29-1. Tags between 19000 and 19999 are not
 | 
			
		||||
allowed. See
 | 
			
		||||
https://developers.google.com/protocol-buffers/docs/proto#assigning-tags
 | 
			
		||||
 | 
			
		||||
#### `invalid_length_exception`
 | 
			
		||||
 | 
			
		||||
This exception is thrown when a length field of a packed repeated field is
 | 
			
		||||
invalid. For fixed size types the length must be a multiple of the size of
 | 
			
		||||
the type.
 | 
			
		||||
 | 
			
		||||
### The `pbf_reader` class
 | 
			
		||||
 | 
			
		||||
The `pbf_reader` class behaves like a value type. Objects are reasonably small
 | 
			
		||||
(two pointers and two `uint32_t`, so 24 bytes on a 64bit system) and they can
 | 
			
		||||
be copied and moved around trivially.
 | 
			
		||||
 | 
			
		||||
`pbf_reader` objects can be constructed from a `std::string` or a `const char*`
 | 
			
		||||
and a length field (either supplied as separate arguments or as a `std::pair`).
 | 
			
		||||
In all cases objects of the `pbf_reader` class store a pointer into the input
 | 
			
		||||
data that was given to the constructor. You have to make sure this pointer
 | 
			
		||||
stays valid for the duration of the objects lifetime.
 | 
			
		||||
 | 
			
		||||
## Parsing protobuf-encoded messages using `pbf_message`
 | 
			
		||||
 | 
			
		||||
One problem in the code above are the "magic numbers" used as tags for the
 | 
			
		||||
different fields that you got from the `.proto` file. Instead of spreading
 | 
			
		||||
these magic numbers around your code you can define them once in an `enum
 | 
			
		||||
class` and then use the `pbf_message` template class instead of the
 | 
			
		||||
`pbf_reader` class.
 | 
			
		||||
 | 
			
		||||
Here is the first example again, this time using this new technique. So you
 | 
			
		||||
have the following in a `.proto` file:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
message Example1 {
 | 
			
		||||
    required uint32 x  =  1;
 | 
			
		||||
    optional string s  =  2;
 | 
			
		||||
    repeated fixed64 r = 17;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Add the following declaration in one of your header files:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
enum class Example1 : protozero::pbf_tag_type {
 | 
			
		||||
    required_uint32_x  =  1,
 | 
			
		||||
    optional_string_s  =  2,
 | 
			
		||||
    repeated_fixed64_r = 17
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The message name becomes the name of the `enum class` which is always built
 | 
			
		||||
on top of the `protozero::pbf_tag_type` type. Each field in the message
 | 
			
		||||
becomes one value of the enum. In this case the name is created from the
 | 
			
		||||
type (including the modifiers like `required` or `optional`) and the name of
 | 
			
		||||
the field. You can use any name you want, but this convention makes it easier
 | 
			
		||||
later, to get everything right.
 | 
			
		||||
 | 
			
		||||
To read messages created according to that description, you will have code that
 | 
			
		||||
looks somewhat like this, this time using `pbf_message` instead of
 | 
			
		||||
`pbf_reader`:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/pbf_message.hpp>
 | 
			
		||||
 | 
			
		||||
// get data from somewhere into the input string
 | 
			
		||||
std::string input = get_input_data();
 | 
			
		||||
 | 
			
		||||
// initialize pbf message with this data
 | 
			
		||||
protozero::pbf_message<Example1> message{input};
 | 
			
		||||
 | 
			
		||||
// iterate over fields in the message
 | 
			
		||||
while (message.next()) {
 | 
			
		||||
 | 
			
		||||
    // switch depending on the field tag (the field name is not available)
 | 
			
		||||
    switch (message.tag()) {
 | 
			
		||||
        case Example1::required_uint32_x:
 | 
			
		||||
            auto x = message.get_uint32();
 | 
			
		||||
            break;
 | 
			
		||||
        case Example1::optional_string_s:
 | 
			
		||||
            std::string s = message.get_string();
 | 
			
		||||
            break;
 | 
			
		||||
        case Example1::repeated_fixed64_r:
 | 
			
		||||
            message.skip();
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            // ignore data for unknown tags to allow for future extensions
 | 
			
		||||
            message.skip();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Note the correspondance between the enum value (for instance
 | 
			
		||||
`required_uint32_x`) and the name of the getter function (for instance
 | 
			
		||||
`get_uint32()`). This makes it easier to get the correct types. Also the
 | 
			
		||||
naming makes it easier to keep different message types apart if you have
 | 
			
		||||
multiple (or embedded) messages.
 | 
			
		||||
 | 
			
		||||
See the `test/t/complex` test case for a complete example using this interface.
 | 
			
		||||
 | 
			
		||||
Using `pbf_message` in favour of `pbf_reader` is recommended for all code.
 | 
			
		||||
Note that `pbf_message` derives from `pbf_reader`, so you can always fall
 | 
			
		||||
back to the more generic interface if necessary.
 | 
			
		||||
 | 
			
		||||
One problem you might run into is the following: The enum class lists all
 | 
			
		||||
possible values you know about and you'll have lots of `switch` statements
 | 
			
		||||
checking those values. Some compilers will know that your `switch` covers
 | 
			
		||||
all possible cases and warn you if you have a `default` case that looks
 | 
			
		||||
unneccessary to the compiler. But you still want that `default` case to allow
 | 
			
		||||
for future extension of those messages (and maybe also to detect corrupted
 | 
			
		||||
data). You can switch of this warning with `-Wno-covered-switch-default`).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Writing protobuf-encoded messages
 | 
			
		||||
 | 
			
		||||
### Using `pbf_writer`
 | 
			
		||||
 | 
			
		||||
To use the `pbf_writer` class, add this include to your C++ program:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/pbf_writer.hpp>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The `pbf_writer` class contains asserts that will detect some programming
 | 
			
		||||
errors. We encourage you to compile with asserts enabled in your debug builds.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### An introductory example
 | 
			
		||||
 | 
			
		||||
Lets say you have a protocol description in a `.proto` file like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
message Example {
 | 
			
		||||
    required uint32 x = 1;
 | 
			
		||||
    optional string s = 2;
 | 
			
		||||
    repeated fixed64 r = 17;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
To write messages created according to that description, you will have code
 | 
			
		||||
that looks somewhat like this:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
#include <protozero/pbf_writer.hpp>
 | 
			
		||||
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pbf_example{data};
 | 
			
		||||
 | 
			
		||||
pbf_example.add_uint32(1, 27);       // uint32_t x
 | 
			
		||||
pbf_example.add_fixed64(17, 1);      // fixed64 r
 | 
			
		||||
pbf_example.add_fixed64(17, 2);
 | 
			
		||||
pbf_example.add_fixed64(17, 3);
 | 
			
		||||
pbf_example.add_string(2, "foobar"); // string s
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
First you need a string which will be used as buffer to assemble the
 | 
			
		||||
protobuf-formatted message. The `pbf_writer` object contains a reference to
 | 
			
		||||
this string buffer and through it you add data to that buffer piece by piece.
 | 
			
		||||
The buffer doesn't have to be empty, the `pbf_writer` will simply append its
 | 
			
		||||
data to whatever is there already.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Handling scalar fields
 | 
			
		||||
 | 
			
		||||
As you could see in the introductory example handling any kind of scalar field
 | 
			
		||||
is easy. The type of field doesn't matter and it doesn't matter whether it is
 | 
			
		||||
optional, required or repeated. You always call one of the `add_TYPE()` method
 | 
			
		||||
on the pbf writer object.
 | 
			
		||||
 | 
			
		||||
The first parameter of these methods is always the *tag* of the field (the
 | 
			
		||||
field number) from the `.proto` file. The second parameter is the value you
 | 
			
		||||
want to set. For the `bytes` and `string` types several versions of the add
 | 
			
		||||
method are available taking a `const std::string&` or a `const char*` and a
 | 
			
		||||
length.
 | 
			
		||||
 | 
			
		||||
For `enum` types you have to use the numeric value as the symbolic names from
 | 
			
		||||
the `.proto` file are not available.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Handling repeated packed fields
 | 
			
		||||
 | 
			
		||||
Repeated packed fields can easily be set from a pair of iterators:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pw{data};
 | 
			
		||||
 | 
			
		||||
std::vector<int> v = { 1, 4, 9, 16, 25, 36 };
 | 
			
		||||
pw.add_packed_int32(1, std::begin(v), std::end(v));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you don't have an iterator you can use the alternative form:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pw{data};
 | 
			
		||||
{
 | 
			
		||||
    protozero::packed_field_int32 field{pw, 1};
 | 
			
		||||
    field.add_element(1);
 | 
			
		||||
    field.add_element(10);
 | 
			
		||||
    field.add_element(100);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Of course you can add as many elements as you want. If you add no elements
 | 
			
		||||
at all, this code will still work, Protozero detects this special case and
 | 
			
		||||
pretends you never even initialized this field.
 | 
			
		||||
 | 
			
		||||
The nested scope is important in this case, because the destructor of the
 | 
			
		||||
`field` object will make sure the length stored inside the field is set to
 | 
			
		||||
the right value. You must close that scope before adding other fields to the
 | 
			
		||||
`pw` pbf writer.
 | 
			
		||||
 | 
			
		||||
If you know how many elements you will add to the field and your field contains
 | 
			
		||||
fixed length elements, you can tell Protozero and it can optimize this case:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pw{data};
 | 
			
		||||
{
 | 
			
		||||
    protozero::packed_field_fixed32 field{pw, 1, 2}; // exactly two elements
 | 
			
		||||
    field.add_element(42);
 | 
			
		||||
    field.add_element(13);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In this case you have to supply exactly as many elements as you promised,
 | 
			
		||||
otherwise you will get a broken protobuf message.
 | 
			
		||||
 | 
			
		||||
This works for `packed_field_fixed32`, `packed_field_sfixed32`,
 | 
			
		||||
`packed_field_fixed64`, `packed_field_sfixed64`, `packed_field_float`, and
 | 
			
		||||
`packed_field_double`.
 | 
			
		||||
 | 
			
		||||
You can abandon writing of the packed field if this becomes necessary by
 | 
			
		||||
calling `rollback()`:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pw{data};
 | 
			
		||||
{
 | 
			
		||||
    protozero::packed_field_int32 field{pw, 1};
 | 
			
		||||
    field.add_element(42);
 | 
			
		||||
    // some error occurs, you don't want to have this field at all
 | 
			
		||||
    field.rollback();
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The result is the same as if the lines inside the nested brackets had never
 | 
			
		||||
been called. Do not try to call `add_element()` after a rollback.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Handling sub-messages
 | 
			
		||||
 | 
			
		||||
Nested sub-messages can be handled by first creating the submessage and then
 | 
			
		||||
adding to the parent message:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string buffer_sub;
 | 
			
		||||
protozero::pbf_writer pbf_sub{buffer_sub};
 | 
			
		||||
 | 
			
		||||
// add fields to sub-message
 | 
			
		||||
pbf_sub.add_...(...);
 | 
			
		||||
// ...
 | 
			
		||||
 | 
			
		||||
// sub-message is finished here
 | 
			
		||||
 | 
			
		||||
std::string buffer_parent;
 | 
			
		||||
protozero::pbf_writer pbf_parent{buffer_parent};
 | 
			
		||||
pbf_parent.add_message(1, buffer_sub);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is easy to do but it has the drawback of needing a separate `std::string`
 | 
			
		||||
buffer. If this concerns you (and why would you use protozero and not the
 | 
			
		||||
Google protobuf library if it doesn't?) there is another way:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pbf_parent{data};
 | 
			
		||||
 | 
			
		||||
// optionally add fields to parent here
 | 
			
		||||
pbf_parent.add_...(...);
 | 
			
		||||
 | 
			
		||||
// open a new scope
 | 
			
		||||
{
 | 
			
		||||
    // create new pbf_writer with parent and the tag (field number)
 | 
			
		||||
    // as parameters
 | 
			
		||||
    protozero::pbf_writer pbf_sub{pbf_parent, 1};
 | 
			
		||||
 | 
			
		||||
    // add fields to sub here...
 | 
			
		||||
    pbf_sub.add_...(...);
 | 
			
		||||
 | 
			
		||||
} // closing the scope will close the sub-message
 | 
			
		||||
 | 
			
		||||
// optionally add more fields to parent here
 | 
			
		||||
pbf_parent.add_...(...);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This can be nested arbitrarily deep.
 | 
			
		||||
 | 
			
		||||
Internally the sub-message writer re-uses the buffer from the parent. It
 | 
			
		||||
reserves enough space in the buffer to later write the length of the submessage
 | 
			
		||||
into it. It then adds the contents of the submessage to the buffer. When the
 | 
			
		||||
`pbf_sub` writer is destructed the length of the submessage is calculated and
 | 
			
		||||
written in the reserved space. If less space was needed for the length field
 | 
			
		||||
than was available, the rest of the buffer is moved over a few bytes.
 | 
			
		||||
 | 
			
		||||
You can abandon writing of submessage if this becomes necessary by
 | 
			
		||||
calling `rollback()`:
 | 
			
		||||
 | 
			
		||||
```cpp
 | 
			
		||||
std::string data;
 | 
			
		||||
protozero::pbf_writer pbf_parent{data};
 | 
			
		||||
 | 
			
		||||
// open a new scope
 | 
			
		||||
{
 | 
			
		||||
    // create new pbf_writer with parent and the tag (field number)
 | 
			
		||||
    // as parameters
 | 
			
		||||
    protozero::pbf_writer pbf_sub{pbf_parent, 1};
 | 
			
		||||
 | 
			
		||||
    // add fields to sub here...
 | 
			
		||||
    pbf_sub.add_...(...);
 | 
			
		||||
 | 
			
		||||
    // some problem occurs and you want to abandon the submessage:
 | 
			
		||||
    pbf_sub.rollback();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// optionally add more fields to parent here
 | 
			
		||||
pbf_parent.add_...(...);
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The result is the same as if the lines inside the nested brackets had never
 | 
			
		||||
been called. Do not try to call any of the `add_*` functions on the submessage
 | 
			
		||||
after a rollback.
 | 
			
		||||
 | 
			
		||||
## Writing protobuf-encoded messages using `pbf_builder`
 | 
			
		||||
 | 
			
		||||
Just like the `pbf_message` template class wraps the `pbf_reader` class, there
 | 
			
		||||
is a `pbf_builder` template class wrapping the `pbf_writer` class. It is
 | 
			
		||||
instantiated using the same `enum class` described above and used exactly
 | 
			
		||||
like the `pbf_writer` class but using the values of the enum instead of bare
 | 
			
		||||
integers.
 | 
			
		||||
 | 
			
		||||
See the `test/t/complex` test case for a complete example using this interface.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										83
									
								
								third_party/protozero/include/protozero/byteswap.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								third_party/protozero/include/protozero/byteswap.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
#ifndef PROTOZERO_BYTESWAP_HPP
 | 
			
		||||
#define PROTOZERO_BYTESWAP_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 byteswap.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains functions to swap bytes in values (for different endianness).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/config.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(uint32_t* ptr) noexcept {
 | 
			
		||||
    *ptr = byteswap_impl(*ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(uint64_t* ptr) noexcept {
 | 
			
		||||
    *ptr = byteswap_impl(*ptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(int32_t* ptr) noexcept {
 | 
			
		||||
    auto bptr = reinterpret_cast<uint32_t*>(ptr);
 | 
			
		||||
    *bptr = byteswap_impl(*bptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(int64_t* ptr) noexcept {
 | 
			
		||||
    auto bptr = reinterpret_cast<uint64_t*>(ptr);
 | 
			
		||||
    *bptr = byteswap_impl(*bptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(float* ptr) noexcept {
 | 
			
		||||
    auto bptr = reinterpret_cast<uint32_t*>(ptr);
 | 
			
		||||
    *bptr = byteswap_impl(*bptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void byteswap_inplace(double* ptr) noexcept {
 | 
			
		||||
    auto bptr = reinterpret_cast<uint64_t*>(ptr);
 | 
			
		||||
    *bptr = byteswap_impl(*bptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // end namespace detail
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_BYTESWAP_HPP
 | 
			
		||||
							
								
								
									
										48
									
								
								third_party/protozero/include/protozero/config.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								third_party/protozero/include/protozero/config.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
#ifndef PROTOZERO_CONFIG_HPP
 | 
			
		||||
#define PROTOZERO_CONFIG_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.
 | 
			
		||||
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file config.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains macro checks for different configurations.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PROTOZERO_LITTLE_ENDIAN 1234
 | 
			
		||||
#define PROTOZERO_BIG_ENDIAN    4321
 | 
			
		||||
 | 
			
		||||
// Find out which byte order the machine has.
 | 
			
		||||
#if defined(__BYTE_ORDER)
 | 
			
		||||
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
 | 
			
		||||
#  define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
# endif
 | 
			
		||||
# if (__BYTE_ORDER == __BIG_ENDIAN)
 | 
			
		||||
#  define PROTOZERO_BYTE_ORDER PROTOZERO_BIG_ENDIAN
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
// This probably isn't a very good default, but might do until we figure
 | 
			
		||||
// out something better.
 | 
			
		||||
# define PROTOZERO_BYTE_ORDER PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Check whether __builtin_bswap is available
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
# define PROTOZERO_USE_BUILTIN_BSWAP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Wrapper for assert() used for testing
 | 
			
		||||
#ifndef protozero_assert
 | 
			
		||||
# define protozero_assert(x) assert(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_CONFIG_HPP
 | 
			
		||||
							
								
								
									
										236
									
								
								third_party/protozero/include/protozero/data_view.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								third_party/protozero/include/protozero/data_view.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,236 @@
 | 
			
		||||
#ifndef PROTOZERO_DATA_VIEW_HPP
 | 
			
		||||
#define PROTOZERO_DATA_VIEW_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 data_view.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the implementation of the data_view class.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/config.hpp>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
#ifdef PROTOZERO_USE_VIEW
 | 
			
		||||
using data_view = PROTOZERO_USE_VIEW;
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Holds a pointer to some data and a length.
 | 
			
		||||
 *
 | 
			
		||||
 * This class is supposed to be compatible with the std::string_view
 | 
			
		||||
 * that will be available in C++17.
 | 
			
		||||
 */
 | 
			
		||||
class data_view {
 | 
			
		||||
 | 
			
		||||
    const char* m_data = nullptr;
 | 
			
		||||
    std::size_t m_size = 0;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Default constructor. Construct an empty data_view.
 | 
			
		||||
     */
 | 
			
		||||
    constexpr data_view() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create data_view from pointer and size.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ptr Pointer to the data.
 | 
			
		||||
     * @param length Length of the data.
 | 
			
		||||
     */
 | 
			
		||||
    constexpr data_view(const char* ptr, std::size_t length) noexcept
 | 
			
		||||
        : m_data(ptr),
 | 
			
		||||
          m_size(length) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create data_view from string.
 | 
			
		||||
     *
 | 
			
		||||
     * @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()) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create data_view from zero-terminated string.
 | 
			
		||||
     *
 | 
			
		||||
     * @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)) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Swap the contents of this object with the other.
 | 
			
		||||
     *
 | 
			
		||||
     * @param other Other object to swap data with.
 | 
			
		||||
     */
 | 
			
		||||
    void swap(data_view& other) noexcept {
 | 
			
		||||
        using std::swap;
 | 
			
		||||
        swap(m_data, other.m_data);
 | 
			
		||||
        swap(m_size, other.m_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return pointer to data.
 | 
			
		||||
    constexpr const char* data() const noexcept {
 | 
			
		||||
        return m_data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return length of data in bytes.
 | 
			
		||||
    constexpr std::size_t size() const noexcept {
 | 
			
		||||
        return m_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns true if size is 0.
 | 
			
		||||
    constexpr bool empty() const noexcept {
 | 
			
		||||
        return m_size == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef PROTOZERO_STRICT_API
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert data view to string.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre Must not be default constructed data_view.
 | 
			
		||||
     *
 | 
			
		||||
     * @deprecated to_string() is not available in C++17 string_view so it
 | 
			
		||||
     *             should not be used to make conversion to that class easier
 | 
			
		||||
     *             in the future.
 | 
			
		||||
     */
 | 
			
		||||
    std::string to_string() const {
 | 
			
		||||
        protozero_assert(m_data);
 | 
			
		||||
        return {m_data, m_size};
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert data view to string.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre Must not be default constructed data_view.
 | 
			
		||||
     */
 | 
			
		||||
    explicit operator std::string() const {
 | 
			
		||||
        protozero_assert(m_data);
 | 
			
		||||
        return {m_data, m_size};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Compares the contents of this object with the given other object.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns 0 if they are the same, <0 if this object is smaller than
 | 
			
		||||
     *          the other or >0 if it is larger. If both objects have the
 | 
			
		||||
     *          same size returns <0 if this object is lexicographically
 | 
			
		||||
     *          before the other, >0 otherwise.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre Must not be default constructed data_view.
 | 
			
		||||
     */
 | 
			
		||||
    int compare(data_view other) const {
 | 
			
		||||
        protozero_assert(m_data && other.m_data);
 | 
			
		||||
        const int cmp = std::memcmp(data(), other.data(),
 | 
			
		||||
                                    std::min(size(), other.size()));
 | 
			
		||||
        if (cmp == 0) {
 | 
			
		||||
            if (size() == other.size()) {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
            return size() < other.size() ? -1 : 1;
 | 
			
		||||
        }
 | 
			
		||||
        return cmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // class data_view
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Swap two data_view objects.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline void swap(data_view& lhs, data_view& rhs) noexcept {
 | 
			
		||||
    lhs.swap(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Two data_view instances are equal if they have the same size and the
 | 
			
		||||
 * same content.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline constexpr bool operator==(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return lhs.size() == rhs.size() &&
 | 
			
		||||
           std::equal(lhs.data(), lhs.data() + lhs.size(), rhs.data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Two data_view instances are not equal if they have different sizes or the
 | 
			
		||||
 * content differs.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline constexpr bool operator!=(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return !(lhs == rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns true if lhs.compare(rhs) < 0.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline bool operator<(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return lhs.compare(rhs) < 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns true if lhs.compare(rhs) <= 0.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline bool operator<=(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return lhs.compare(rhs) <= 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns true if lhs.compare(rhs) > 0.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline bool operator>(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return lhs.compare(rhs) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns true if lhs.compare(rhs) >= 0.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline bool operator>=(const data_view lhs, const data_view rhs) noexcept {
 | 
			
		||||
    return lhs.compare(rhs) >= 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_DATA_VIEW_HPP
 | 
			
		||||
							
								
								
									
										101
									
								
								third_party/protozero/include/protozero/exception.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								third_party/protozero/include/protozero/exception.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
#ifndef PROTOZERO_EXCEPTION_HPP
 | 
			
		||||
#define PROTOZERO_EXCEPTION_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 exception.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the exceptions used in the protozero library.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <exception>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief All parts of the protozero header-only library are in this namespace.
 | 
			
		||||
 */
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * All exceptions explicitly thrown by the functions of the protozero library
 | 
			
		||||
 * derive from this exception.
 | 
			
		||||
 */
 | 
			
		||||
struct exception : std::exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "pbf exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This exception is thrown when parsing a varint thats larger than allowed.
 | 
			
		||||
 * This should never happen unless the data is corrupted.
 | 
			
		||||
 */
 | 
			
		||||
struct varint_too_long_exception : exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "varint too long exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This exception is thrown when the wire type of a pdf field is unknown.
 | 
			
		||||
 * This should never happen unless the data is corrupted.
 | 
			
		||||
 */
 | 
			
		||||
struct unknown_pbf_wire_type_exception : exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "unknown pbf field type exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This exception is thrown when we are trying to read a field and there
 | 
			
		||||
 * are not enough bytes left in the buffer to read it. Almost all functions
 | 
			
		||||
 * of the pbf_reader class can throw this exception.
 | 
			
		||||
 *
 | 
			
		||||
 * This should never happen unless the data is corrupted or you have
 | 
			
		||||
 * initialized the pbf_reader object with incomplete data.
 | 
			
		||||
 */
 | 
			
		||||
struct end_of_buffer_exception : exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "end of buffer exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This exception is thrown when a tag has an invalid value. Tags must be
 | 
			
		||||
 * unsigned integers between 1 and 2^29-1. Tags between 19000 and 19999 are
 | 
			
		||||
 * not allowed. See
 | 
			
		||||
 * https://developers.google.com/protocol-buffers/docs/proto#assigning-tags
 | 
			
		||||
 */
 | 
			
		||||
struct invalid_tag_exception : exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "invalid tag exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This exception is thrown when a length field of a packed repeated field is
 | 
			
		||||
 * invalid. For fixed size types the length must be a multiple of the size of
 | 
			
		||||
 * the type.
 | 
			
		||||
 */
 | 
			
		||||
struct invalid_length_exception : exception {
 | 
			
		||||
    /// Returns the explanatory string.
 | 
			
		||||
    const char* what() const noexcept override {
 | 
			
		||||
        return "invalid length exception";
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_EXCEPTION_HPP
 | 
			
		||||
							
								
								
									
										455
									
								
								third_party/protozero/include/protozero/iterators.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								third_party/protozero/include/protozero/iterators.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,455 @@
 | 
			
		||||
#ifndef PROTOZERO_ITERATORS_HPP
 | 
			
		||||
#define PROTOZERO_ITERATORS_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 iterators.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the iterators for access to packed repeated fields.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/config.hpp>
 | 
			
		||||
#include <protozero/varint.hpp>
 | 
			
		||||
 | 
			
		||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
# include <protozero/byteswap.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A range of iterators based on std::pair. Created from beginning and
 | 
			
		||||
 * end iterators. Used as a return type from some pbf_reader methods
 | 
			
		||||
 * that is easy to use with range-based for loops.
 | 
			
		||||
 */
 | 
			
		||||
template <typename T, typename P = std::pair<T, T>>
 | 
			
		||||
class iterator_range :
 | 
			
		||||
#ifdef PROTOZERO_STRICT_API
 | 
			
		||||
    protected
 | 
			
		||||
#else
 | 
			
		||||
    public
 | 
			
		||||
#endif
 | 
			
		||||
        P {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /// The type of the iterators in this range.
 | 
			
		||||
    using iterator = T;
 | 
			
		||||
 | 
			
		||||
    /// The value type of the underlying iterator.
 | 
			
		||||
    using value_type = typename std::iterator_traits<T>::value_type;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Default constructor. Create empty iterator_range.
 | 
			
		||||
     */
 | 
			
		||||
    constexpr iterator_range() :
 | 
			
		||||
        P(iterator{}, iterator{}) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create iterator range from two iterators.
 | 
			
		||||
     *
 | 
			
		||||
     * @param first_iterator Iterator to beginning of range.
 | 
			
		||||
     * @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)) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return iterator to beginning of range.
 | 
			
		||||
    constexpr iterator begin() const noexcept {
 | 
			
		||||
        return this->first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return iterator to end of range.
 | 
			
		||||
    constexpr iterator end() const noexcept {
 | 
			
		||||
        return this->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return iterator to beginning of range.
 | 
			
		||||
    constexpr iterator cbegin() const noexcept {
 | 
			
		||||
        return this->first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Return iterator to end of range.
 | 
			
		||||
    constexpr iterator cend() const noexcept {
 | 
			
		||||
        return this->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return true if this range is empty.
 | 
			
		||||
     *
 | 
			
		||||
     * Complexity: Constant.
 | 
			
		||||
     */
 | 
			
		||||
    constexpr bool empty() const noexcept {
 | 
			
		||||
        return begin() == end();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the size of the range, ie the number of elements it contains.
 | 
			
		||||
     *
 | 
			
		||||
     * Complexity: Constant or linear depending on the underlaying iterator.
 | 
			
		||||
     */
 | 
			
		||||
    std::size_t size() const noexcept {
 | 
			
		||||
        return static_cast<size_t>(std::distance(begin(), end()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get element at the beginning of the range.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre Range must not be empty.
 | 
			
		||||
     */
 | 
			
		||||
    value_type front() const {
 | 
			
		||||
        protozero_assert(!empty());
 | 
			
		||||
        return *(this->first);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Advance beginning of range by one.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre Range must not be empty.
 | 
			
		||||
     */
 | 
			
		||||
    void drop_front() {
 | 
			
		||||
        protozero_assert(!empty());
 | 
			
		||||
        ++this->first;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Swap the contents of this range with the other.
 | 
			
		||||
     *
 | 
			
		||||
     * @param other Other range to swap data with.
 | 
			
		||||
     */
 | 
			
		||||
    void swap(iterator_range& other) noexcept {
 | 
			
		||||
        using std::swap;
 | 
			
		||||
        swap(this->first, other.first);
 | 
			
		||||
        swap(this->second, other.second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // struct iterator_range
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Swap two iterator_ranges.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First range.
 | 
			
		||||
 * @param rhs Second range.
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
inline void swap(iterator_range<T>& lhs, iterator_range<T>& rhs) noexcept {
 | 
			
		||||
    lhs.swap(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A forward iterator used for accessing packed repeated fields of fixed
 | 
			
		||||
 * length (fixed32, sfixed32, float, double).
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
class const_fixed_iterator {
 | 
			
		||||
 | 
			
		||||
    /// Pointer to current iterator position
 | 
			
		||||
    const char* m_data = nullptr;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    using iterator_category = std::random_access_iterator_tag;
 | 
			
		||||
    using value_type        = T;
 | 
			
		||||
    using difference_type   = std::ptrdiff_t;
 | 
			
		||||
    using pointer           = value_type*;
 | 
			
		||||
    using reference         = value_type&;
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    explicit const_fixed_iterator(const char* data) noexcept :
 | 
			
		||||
        m_data(data) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator(const const_fixed_iterator&) noexcept = default;
 | 
			
		||||
    const_fixed_iterator(const_fixed_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator& operator=(const const_fixed_iterator&) noexcept = default;
 | 
			
		||||
    const_fixed_iterator& operator=(const_fixed_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    ~const_fixed_iterator() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    value_type operator*() const {
 | 
			
		||||
        value_type result;
 | 
			
		||||
        std::memcpy(&result, m_data, sizeof(value_type));
 | 
			
		||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
        detail::byteswap_inplace(&result);
 | 
			
		||||
#endif
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator& operator++() noexcept {
 | 
			
		||||
        m_data += sizeof(value_type);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator operator++(int) noexcept {
 | 
			
		||||
        const const_fixed_iterator tmp{*this};
 | 
			
		||||
        ++(*this);
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator operator--(int) noexcept {
 | 
			
		||||
        const const_fixed_iterator tmp{*this};
 | 
			
		||||
        --(*this);
 | 
			
		||||
        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 rhs < lhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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 < rhs);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator& operator+=(difference_type val) noexcept {
 | 
			
		||||
        m_data += (sizeof(value_type) * val);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend const_fixed_iterator operator+(const_fixed_iterator lhs, difference_type rhs) noexcept {
 | 
			
		||||
        const_fixed_iterator tmp{lhs};
 | 
			
		||||
        tmp.m_data += (sizeof(value_type) * rhs);
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend const_fixed_iterator operator+(difference_type lhs, const_fixed_iterator rhs) noexcept {
 | 
			
		||||
        const_fixed_iterator tmp{rhs};
 | 
			
		||||
        tmp.m_data += (sizeof(value_type) * lhs);
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_fixed_iterator& operator-=(difference_type val) noexcept {
 | 
			
		||||
        m_data -= (sizeof(value_type) * val);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend const_fixed_iterator operator-(const_fixed_iterator lhs, difference_type rhs) noexcept {
 | 
			
		||||
        const_fixed_iterator tmp{lhs};
 | 
			
		||||
        tmp.m_data -= (sizeof(value_type) * rhs);
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    friend difference_type operator-(const_fixed_iterator lhs, const_fixed_iterator rhs) noexcept {
 | 
			
		||||
        return static_cast<difference_type>(lhs.m_data - rhs.m_data) / static_cast<difference_type>(sizeof(T));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    value_type operator[](difference_type n) const noexcept {
 | 
			
		||||
        return *(*this + n);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // class const_fixed_iterator
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A forward iterator used for accessing packed repeated varint fields
 | 
			
		||||
 * (int32, uint32, int64, uint64, bool, enum).
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
class const_varint_iterator {
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    /// Pointer to current iterator position
 | 
			
		||||
    const char* m_data = nullptr;
 | 
			
		||||
 | 
			
		||||
    /// Pointer to end iterator position
 | 
			
		||||
    const char* m_end = nullptr;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    using iterator_category = std::forward_iterator_tag;
 | 
			
		||||
    using value_type        = T;
 | 
			
		||||
    using difference_type   = std::ptrdiff_t;
 | 
			
		||||
    using pointer           = value_type*;
 | 
			
		||||
    using reference         = value_type&;
 | 
			
		||||
 | 
			
		||||
    static difference_type distance(const_varint_iterator begin, const_varint_iterator end) noexcept {
 | 
			
		||||
        // 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;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator(const char* data, const char* end) noexcept :
 | 
			
		||||
        m_data(data),
 | 
			
		||||
        m_end(end) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator(const const_varint_iterator&) noexcept = default;
 | 
			
		||||
    const_varint_iterator(const_varint_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator& operator=(const const_varint_iterator&) noexcept = default;
 | 
			
		||||
    const_varint_iterator& operator=(const_varint_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    ~const_varint_iterator() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    value_type operator*() const {
 | 
			
		||||
        const char* d = m_data; // will be thrown away
 | 
			
		||||
        return static_cast<value_type>(decode_varint(&d, m_end));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator& operator++() {
 | 
			
		||||
        skip_varint(&m_data, m_end);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_varint_iterator operator++(int) {
 | 
			
		||||
        const const_varint_iterator tmp{*this};
 | 
			
		||||
        ++(*this);
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator==(const const_varint_iterator& rhs) const noexcept {
 | 
			
		||||
        return m_data == rhs.m_data && m_end == rhs.m_end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator!=(const const_varint_iterator& rhs) const noexcept {
 | 
			
		||||
        return !(*this == rhs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // class const_varint_iterator
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A forward iterator used for accessing packed repeated svarint fields
 | 
			
		||||
 * (sint32, sint64).
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
class const_svarint_iterator : public const_varint_iterator<T> {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    using iterator_category = std::forward_iterator_tag;
 | 
			
		||||
    using value_type        = T;
 | 
			
		||||
    using difference_type   = std::ptrdiff_t;
 | 
			
		||||
    using pointer           = value_type*;
 | 
			
		||||
    using reference         = value_type&;
 | 
			
		||||
 | 
			
		||||
    const_svarint_iterator() noexcept :
 | 
			
		||||
        const_varint_iterator<T>() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_svarint_iterator(const char* data, const char* end) noexcept :
 | 
			
		||||
        const_varint_iterator<T>(data, end) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_svarint_iterator(const const_svarint_iterator&) = default;
 | 
			
		||||
    const_svarint_iterator(const_svarint_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    const_svarint_iterator& operator=(const const_svarint_iterator&) = default;
 | 
			
		||||
    const_svarint_iterator& operator=(const_svarint_iterator&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    ~const_svarint_iterator() = default;
 | 
			
		||||
 | 
			
		||||
    value_type operator*() const {
 | 
			
		||||
        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++() {
 | 
			
		||||
        skip_varint(&this->m_data, this->m_end);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const_svarint_iterator operator++(int) {
 | 
			
		||||
        const const_svarint_iterator tmp{*this};
 | 
			
		||||
        ++(*this);
 | 
			
		||||
        return tmp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // class const_svarint_iterator
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
namespace std {
 | 
			
		||||
 | 
			
		||||
    // Specialize std::distance for all the protozero iterators. Because
 | 
			
		||||
    // functions can't be partially specialized, we have to do this for
 | 
			
		||||
    // every value_type we are using.
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
                                                        protozero::const_varint_iterator<int32_t> last) {
 | 
			
		||||
        return protozero::const_varint_iterator<int32_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <>
 | 
			
		||||
    inline typename protozero::const_varint_iterator<int64_t>::difference_type
 | 
			
		||||
    distance<protozero::const_varint_iterator<int64_t>>(protozero::const_varint_iterator<int64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
 | 
			
		||||
                                                        protozero::const_varint_iterator<int64_t> last) {
 | 
			
		||||
        return protozero::const_varint_iterator<int64_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <>
 | 
			
		||||
    inline typename protozero::const_varint_iterator<uint32_t>::difference_type
 | 
			
		||||
    distance<protozero::const_varint_iterator<uint32_t>>(protozero::const_varint_iterator<uint32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
 | 
			
		||||
                                                         protozero::const_varint_iterator<uint32_t> last) {
 | 
			
		||||
        return protozero::const_varint_iterator<uint32_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <>
 | 
			
		||||
    inline typename protozero::const_varint_iterator<uint64_t>::difference_type
 | 
			
		||||
    distance<protozero::const_varint_iterator<uint64_t>>(protozero::const_varint_iterator<uint64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
 | 
			
		||||
                                                         protozero::const_varint_iterator<uint64_t> last) {
 | 
			
		||||
        return protozero::const_varint_iterator<uint64_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <>
 | 
			
		||||
    inline typename protozero::const_svarint_iterator<int32_t>::difference_type
 | 
			
		||||
    distance<protozero::const_svarint_iterator<int32_t>>(protozero::const_svarint_iterator<int32_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
 | 
			
		||||
                                                         protozero::const_svarint_iterator<int32_t> last) {
 | 
			
		||||
        return protozero::const_svarint_iterator<int32_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <>
 | 
			
		||||
    inline typename protozero::const_svarint_iterator<int64_t>::difference_type
 | 
			
		||||
    distance<protozero::const_svarint_iterator<int64_t>>(protozero::const_svarint_iterator<int64_t> first, // NOLINT(readability-inconsistent-declaration-parameter-name)
 | 
			
		||||
                                                         protozero::const_svarint_iterator<int64_t> last) {
 | 
			
		||||
        return protozero::const_svarint_iterator<int64_t>::distance(first, last);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} // end namespace std
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_ITERATORS_HPP
 | 
			
		||||
							
								
								
									
										265
									
								
								third_party/protozero/include/protozero/pbf_builder.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										265
									
								
								third_party/protozero/include/protozero/pbf_builder.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,265 @@
 | 
			
		||||
#ifndef PROTOZERO_PBF_BUILDER_HPP
 | 
			
		||||
#define PROTOZERO_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 pbf_builder.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the pbf_builder template class.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/pbf_writer.hpp>
 | 
			
		||||
#include <protozero/types.hpp>
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 */
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_PBF_BUILDER_HPP
 | 
			
		||||
							
								
								
									
										184
									
								
								third_party/protozero/include/protozero/pbf_message.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								third_party/protozero/include/protozero/pbf_message.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,184 @@
 | 
			
		||||
#ifndef PROTOZERO_PBF_MESSAGE_HPP
 | 
			
		||||
#define PROTOZERO_PBF_MESSAGE_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 pbf_message.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the pbf_message template class.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/pbf_reader.hpp>
 | 
			
		||||
#include <protozero/types.hpp>
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class represents a protobuf message. Either a top-level message or
 | 
			
		||||
 * a nested sub-message. Top-level messages can be created from any buffer
 | 
			
		||||
 * with a pointer and length:
 | 
			
		||||
 *
 | 
			
		||||
 * @code
 | 
			
		||||
 *    enum class Message : protozero::pbf_tag_type {
 | 
			
		||||
 *       ...
 | 
			
		||||
 *    };
 | 
			
		||||
 *
 | 
			
		||||
 *    std::string buffer;
 | 
			
		||||
 *    // fill buffer...
 | 
			
		||||
 *    pbf_message<Message> message{buffer.data(), buffer.size()};
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * Sub-messages are created using get_message():
 | 
			
		||||
 *
 | 
			
		||||
 * @code
 | 
			
		||||
 *    enum class SubMessage : protozero::pbf_tag_type {
 | 
			
		||||
 *       ...
 | 
			
		||||
 *    };
 | 
			
		||||
 *
 | 
			
		||||
 *    pbf_message<Message> message{...};
 | 
			
		||||
 *    message.next();
 | 
			
		||||
 *    pbf_message<SubMessage> submessage = message.get_message();
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * All methods of the pbf_message class except get_bytes() and get_string()
 | 
			
		||||
 * provide the strong exception guarantee, ie they either succeed or do not
 | 
			
		||||
 * change the pbf_message object they are called on. Use the get_data() method
 | 
			
		||||
 * instead of get_bytes() or get_string(), if you need this guarantee.
 | 
			
		||||
 *
 | 
			
		||||
 * This template class is based on the pbf_reader class and has all the same
 | 
			
		||||
 * methods. The difference is that whereever the pbf_reader class takes an
 | 
			
		||||
 * integer tag, this template class takes a tag of the template type T.
 | 
			
		||||
 *
 | 
			
		||||
 * Read the tutorial to understand how this class is used.
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
class pbf_message : public pbf_reader {
 | 
			
		||||
 | 
			
		||||
    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 read.
 | 
			
		||||
    using enum_type = T;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a pbf_message. All arguments are forwarded to the pbf_reader
 | 
			
		||||
     * parent class.
 | 
			
		||||
     */
 | 
			
		||||
    template <typename... Args>
 | 
			
		||||
    pbf_message(Args&&... args) noexcept : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
 | 
			
		||||
        pbf_reader(std::forward<Args>(args)...) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field in the message as the current field. This is usually
 | 
			
		||||
     * called in a while loop:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_message<...> message(...);
 | 
			
		||||
     *    while (message.next()) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field, `false` if not.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now.
 | 
			
		||||
     */
 | 
			
		||||
    bool next() {
 | 
			
		||||
        return pbf_reader::next();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field with given tag in the message as the current field.
 | 
			
		||||
     * Fields with other tags are skipped. This is usually called in a while
 | 
			
		||||
     * loop for repeated fields:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_message<Example1> message{...};
 | 
			
		||||
     *    while (message.next(Example1::repeated_fixed64_r)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * or you can call it just once to get the one field with this tag:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_message<Example1> message{...};
 | 
			
		||||
     *    if (message.next(Example1::required_uint32_x)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * Note that this will not check the wire type. The two-argument version
 | 
			
		||||
     * of this function will also check the wire type.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field with this tag.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now with the given tag.
 | 
			
		||||
     */
 | 
			
		||||
    bool next(T next_tag) {
 | 
			
		||||
        return pbf_reader::next(pbf_tag_type(next_tag));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field with given tag and wire type in the message as the
 | 
			
		||||
     * current field. Fields with other tags are skipped. This is usually
 | 
			
		||||
     * called in a while loop for repeated fields:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_message<Example1> message{...};
 | 
			
		||||
     *    while (message.next(Example1::repeated_fixed64_r, pbf_wire_type::varint)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * or you can call it just once to get the one field with this tag:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_message<Example1> message{...};
 | 
			
		||||
     *    if (message.next(Example1::required_uint32_x, pbf_wire_type::varint)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * Note that this will also check the wire type. The one-argument version
 | 
			
		||||
     * of this function will not check the wire type.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field with this tag.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now with the given tag.
 | 
			
		||||
     */
 | 
			
		||||
    bool next(T next_tag, pbf_wire_type type) {
 | 
			
		||||
        return pbf_reader::next(pbf_tag_type(next_tag), type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The tag of the current field. The tag is the enum value for the field
 | 
			
		||||
     * number from the description in the .proto file.
 | 
			
		||||
     *
 | 
			
		||||
     * Call next() before calling this function to set the current field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns tag of the current field.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     */
 | 
			
		||||
    T tag() const noexcept {
 | 
			
		||||
        return T(pbf_reader::tag());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}; // class pbf_message
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_PBF_MESSAGE_HPP
 | 
			
		||||
							
								
								
									
										969
									
								
								third_party/protozero/include/protozero/pbf_reader.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										969
									
								
								third_party/protozero/include/protozero/pbf_reader.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,969 @@
 | 
			
		||||
#ifndef PROTOZERO_PBF_READER_HPP
 | 
			
		||||
#define PROTOZERO_PBF_READER_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 pbf_reader.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @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>
 | 
			
		||||
 | 
			
		||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
# include <protozero/byteswap.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class represents a protobuf message. Either a top-level message or
 | 
			
		||||
 * a nested sub-message. Top-level messages can be created from any buffer
 | 
			
		||||
 * with a pointer and length:
 | 
			
		||||
 *
 | 
			
		||||
 * @code
 | 
			
		||||
 *    std::string buffer;
 | 
			
		||||
 *    // fill buffer...
 | 
			
		||||
 *    pbf_reader message{buffer.data(), buffer.size()};
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * Sub-messages are created using get_message():
 | 
			
		||||
 *
 | 
			
		||||
 * @code
 | 
			
		||||
 *    pbf_reader message{...};
 | 
			
		||||
 *    message.next();
 | 
			
		||||
 *    pbf_reader submessage = message.get_message();
 | 
			
		||||
 * @endcode
 | 
			
		||||
 *
 | 
			
		||||
 * All methods of the pbf_reader class except get_bytes() and get_string()
 | 
			
		||||
 * provide the strong exception guarantee, ie they either succeed or do not
 | 
			
		||||
 * change the pbf_reader object they are called on. Use the get_view() method
 | 
			
		||||
 * instead of get_bytes() or get_string(), if you need this guarantee.
 | 
			
		||||
 */
 | 
			
		||||
class pbf_reader {
 | 
			
		||||
 | 
			
		||||
    // A pointer to the next unread data.
 | 
			
		||||
    const char* m_data = nullptr;
 | 
			
		||||
 | 
			
		||||
    // A pointer to one past the end of data.
 | 
			
		||||
    const char* m_end = nullptr;
 | 
			
		||||
 | 
			
		||||
    // The wire type of the current field.
 | 
			
		||||
    pbf_wire_type m_wire_type = pbf_wire_type::unknown;
 | 
			
		||||
 | 
			
		||||
    // The tag of the current field.
 | 
			
		||||
    pbf_tag_type m_tag = 0;
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T get_fixed() {
 | 
			
		||||
        T result;
 | 
			
		||||
        const char* data = m_data;
 | 
			
		||||
        skip_bytes(sizeof(T));
 | 
			
		||||
        std::memcpy(&result, data, sizeof(T));
 | 
			
		||||
#if PROTOZERO_BYTE_ORDER != PROTOZERO_LITTLE_ENDIAN
 | 
			
		||||
        detail::byteswap_inplace(&result);
 | 
			
		||||
#endif
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    iterator_range<const_fixed_iterator<T>> packed_fixed() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        const auto len = get_len_and_skip();
 | 
			
		||||
        if (len % sizeof(T) != 0) {
 | 
			
		||||
            throw invalid_length_exception{};
 | 
			
		||||
        }
 | 
			
		||||
        return {const_fixed_iterator<T>(m_data - len),
 | 
			
		||||
                const_fixed_iterator<T>(m_data)};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T get_varint() {
 | 
			
		||||
        return static_cast<T>(decode_varint(&m_data, m_end));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    T get_svarint() {
 | 
			
		||||
        protozero_assert((has_wire_type(pbf_wire_type::varint) || has_wire_type(pbf_wire_type::length_delimited)) && "not a varint");
 | 
			
		||||
        return static_cast<T>(decode_zigzag64(decode_varint(&m_data, m_end)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pbf_length_type get_length() {
 | 
			
		||||
        return get_varint<pbf_length_type>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void skip_bytes(pbf_length_type len) {
 | 
			
		||||
        if (m_data + len > m_end) {
 | 
			
		||||
            throw end_of_buffer_exception{};
 | 
			
		||||
        }
 | 
			
		||||
        m_data += len;
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
        // In debug builds reset the tag to zero so that we can detect (some)
 | 
			
		||||
        // wrong code.
 | 
			
		||||
        m_tag = 0;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pbf_length_type get_len_and_skip() {
 | 
			
		||||
        const auto len = get_length();
 | 
			
		||||
        skip_bytes(len);
 | 
			
		||||
        return len;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    iterator_range<T> get_packed() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        const auto len = get_len_and_skip();
 | 
			
		||||
        return {T{m_data - len, m_data},
 | 
			
		||||
                T{m_data, m_data}};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a pbf_reader message from a data_view. The pointer from the
 | 
			
		||||
     * data_view will be stored inside the pbf_reader object, no data is
 | 
			
		||||
     * copied. So you must make sure the view stays valid as long as the
 | 
			
		||||
     * pbf_reader object is used.
 | 
			
		||||
     *
 | 
			
		||||
     * The buffer must contain a complete protobuf message.
 | 
			
		||||
     *
 | 
			
		||||
     * @post There is no current field.
 | 
			
		||||
     */
 | 
			
		||||
    explicit pbf_reader(const data_view& view) noexcept
 | 
			
		||||
        : m_data(view.data()),
 | 
			
		||||
          m_end(view.data() + view.size()) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a pbf_reader message from a data pointer and a length. The
 | 
			
		||||
     * pointer will be stored inside the pbf_reader object, no data is copied.
 | 
			
		||||
     * So you must make sure the buffer stays valid as long as the pbf_reader
 | 
			
		||||
     * object is used.
 | 
			
		||||
     *
 | 
			
		||||
     * The buffer must contain a complete protobuf message.
 | 
			
		||||
     *
 | 
			
		||||
     * @post There is no current field.
 | 
			
		||||
     */
 | 
			
		||||
    pbf_reader(const char* data, std::size_t size) noexcept
 | 
			
		||||
        : m_data(data),
 | 
			
		||||
          m_end(data + size) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef PROTOZERO_STRICT_API
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a pbf_reader message from a data pointer and a length. The
 | 
			
		||||
     * pointer will be stored inside the pbf_reader object, no data is copied.
 | 
			
		||||
     * So you must make sure the buffer stays valid as long as the pbf_reader
 | 
			
		||||
     * object is used.
 | 
			
		||||
     *
 | 
			
		||||
     * The buffer must contain a complete protobuf message.
 | 
			
		||||
     *
 | 
			
		||||
     * @post There is no current field.
 | 
			
		||||
     * @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) {
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a pbf_reader message from a std::string. A pointer to the
 | 
			
		||||
     * string internals will be stored inside the pbf_reader object, no data
 | 
			
		||||
     * is copied. So you must make sure the string is unchanged as long as the
 | 
			
		||||
     * pbf_reader object is used.
 | 
			
		||||
     *
 | 
			
		||||
     * The string must contain a complete protobuf message.
 | 
			
		||||
     *
 | 
			
		||||
     * @post There is no current field.
 | 
			
		||||
     */
 | 
			
		||||
    explicit pbf_reader(const std::string& data) noexcept
 | 
			
		||||
        : m_data(data.data()),
 | 
			
		||||
          m_end(data.data() + data.size()) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * pbf_reader can be default constructed and behaves like it has an empty
 | 
			
		||||
     * buffer.
 | 
			
		||||
     */
 | 
			
		||||
    pbf_reader() noexcept = default;
 | 
			
		||||
 | 
			
		||||
    /// pbf_reader messages can be copied trivially.
 | 
			
		||||
    pbf_reader(const pbf_reader&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    /// pbf_reader messages can be moved trivially.
 | 
			
		||||
    pbf_reader(pbf_reader&&) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    /// pbf_reader messages can be copied trivially.
 | 
			
		||||
    pbf_reader& operator=(const pbf_reader& other) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    /// pbf_reader messages can be moved trivially.
 | 
			
		||||
    pbf_reader& operator=(pbf_reader&& other) noexcept = default;
 | 
			
		||||
 | 
			
		||||
    ~pbf_reader() = default;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Swap the contents of this object with the other.
 | 
			
		||||
     *
 | 
			
		||||
     * @param other Other object to swap data with.
 | 
			
		||||
     */
 | 
			
		||||
    void swap(pbf_reader& other) noexcept {
 | 
			
		||||
        using std::swap;
 | 
			
		||||
        swap(m_data, other.m_data);
 | 
			
		||||
        swap(m_end, other.m_end);
 | 
			
		||||
        swap(m_wire_type, other.m_wire_type);
 | 
			
		||||
        swap(m_tag, other.m_tag);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * In a boolean context the pbf_reader class evaluates to `true` if there
 | 
			
		||||
     * are still fields available and to `false` if the last field has been
 | 
			
		||||
     * read.
 | 
			
		||||
     */
 | 
			
		||||
    operator bool() const noexcept { // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
 | 
			
		||||
        return m_data < m_end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return the length in bytes of the current message. If you have
 | 
			
		||||
     * already called next() and/or any of the get_*() functions, this will
 | 
			
		||||
     * return the remaining length.
 | 
			
		||||
     *
 | 
			
		||||
     * This can, for instance, be used to estimate the space needed for a
 | 
			
		||||
     * buffer. Of course you have to know reasonably well what data to expect
 | 
			
		||||
     * and how it is encoded for this number to have any meaning.
 | 
			
		||||
     */
 | 
			
		||||
    std::size_t length() const noexcept {
 | 
			
		||||
        return std::size_t(m_end - m_data);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field in the message as the current field. This is usually
 | 
			
		||||
     * called in a while loop:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message(...);
 | 
			
		||||
     *    while (message.next()) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field, `false` if not.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now.
 | 
			
		||||
     */
 | 
			
		||||
    bool next() {
 | 
			
		||||
        if (m_data == m_end) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto value = get_varint<uint32_t>();
 | 
			
		||||
        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
 | 
			
		||||
        if (m_tag == 0 || (m_tag >= 19000 && m_tag <= 19999)) {
 | 
			
		||||
            throw invalid_tag_exception{};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_wire_type = pbf_wire_type(value & 0x07u);
 | 
			
		||||
        switch (m_wire_type) {
 | 
			
		||||
            case pbf_wire_type::varint:
 | 
			
		||||
            case pbf_wire_type::fixed64:
 | 
			
		||||
            case pbf_wire_type::length_delimited:
 | 
			
		||||
            case pbf_wire_type::fixed32:
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                throw unknown_pbf_wire_type_exception{};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field with given tag in the message as the current field.
 | 
			
		||||
     * Fields with other tags are skipped. This is usually called in a while
 | 
			
		||||
     * loop for repeated fields:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message{...};
 | 
			
		||||
     *    while (message.next(17)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * or you can call it just once to get the one field with this tag:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message{...};
 | 
			
		||||
     *    if (message.next(17)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * Note that this will not check the wire type. The two-argument version
 | 
			
		||||
     * of this function will also check the wire type.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field with this tag.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now with the given tag.
 | 
			
		||||
     */
 | 
			
		||||
    bool next(pbf_tag_type next_tag) {
 | 
			
		||||
        while (next()) {
 | 
			
		||||
            if (m_tag == next_tag) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            skip();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set next field with given tag and wire type in the message as the
 | 
			
		||||
     * current field. Fields with other tags are skipped. This is usually
 | 
			
		||||
     * called in a while loop for repeated fields:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message{...};
 | 
			
		||||
     *    while (message.next(17, pbf_wire_type::varint)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * or you can call it just once to get the one field with this tag:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message{...};
 | 
			
		||||
     *    if (message.next(17, pbf_wire_type::varint)) {
 | 
			
		||||
     *        // handle field
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     *
 | 
			
		||||
     * Note that this will also check the wire type. The one-argument version
 | 
			
		||||
     * of this function will not check the wire type.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if there is a next field with this tag.
 | 
			
		||||
     * @pre There must be no current field.
 | 
			
		||||
     * @post If it returns `true` there is a current field now with the given tag.
 | 
			
		||||
     */
 | 
			
		||||
    bool next(pbf_tag_type next_tag, pbf_wire_type type) {
 | 
			
		||||
        while (next()) {
 | 
			
		||||
            if (m_tag == next_tag && m_wire_type == type) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            skip();
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The tag of the current field. The tag is the field number from the
 | 
			
		||||
     * description in the .proto file.
 | 
			
		||||
     *
 | 
			
		||||
     * Call next() before calling this function to set the current field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns tag of the current field.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     */
 | 
			
		||||
    pbf_tag_type tag() const noexcept {
 | 
			
		||||
        return m_tag;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the wire type of the current field. The wire types are:
 | 
			
		||||
     *
 | 
			
		||||
     * * 0 - varint
 | 
			
		||||
     * * 1 - 64 bit
 | 
			
		||||
     * * 2 - length-delimited
 | 
			
		||||
     * * 5 - 32 bit
 | 
			
		||||
     *
 | 
			
		||||
     * All other types are illegal.
 | 
			
		||||
     *
 | 
			
		||||
     * Call next() before calling this function to set the current field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns wire type of the current field.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     */
 | 
			
		||||
    pbf_wire_type wire_type() const noexcept {
 | 
			
		||||
        return m_wire_type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the tag and wire type of the current field in one integer suitable
 | 
			
		||||
     * for comparison with a switch statement.
 | 
			
		||||
     *
 | 
			
		||||
     * Use it like this:
 | 
			
		||||
     *
 | 
			
		||||
     * @code
 | 
			
		||||
     *    pbf_reader message{...};
 | 
			
		||||
     *    while (message.next()) {
 | 
			
		||||
     *        switch (message.tag_and_type()) {
 | 
			
		||||
     *            case tag_and_type(17, pbf_wire_type::length_delimited):
 | 
			
		||||
     *                ....
 | 
			
		||||
     *                break;
 | 
			
		||||
     *            case tag_and_type(21, pbf_wire_type::varint):
 | 
			
		||||
     *                ....
 | 
			
		||||
     *                break;
 | 
			
		||||
     *            default:
 | 
			
		||||
     *                message.skip();
 | 
			
		||||
     *        }
 | 
			
		||||
     *    }
 | 
			
		||||
     * @endcode
 | 
			
		||||
     */
 | 
			
		||||
    uint32_t tag_and_type() const noexcept {
 | 
			
		||||
        return protozero::tag_and_type(tag(), wire_type());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check the wire type of the current field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns `true` if the current field has the given wire type.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     */
 | 
			
		||||
    bool has_wire_type(pbf_wire_type type) const noexcept {
 | 
			
		||||
        return wire_type() == type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume the current field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    void skip() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before calling skip()");
 | 
			
		||||
        switch (wire_type()) {
 | 
			
		||||
            case pbf_wire_type::varint:
 | 
			
		||||
                skip_varint(&m_data, m_end);
 | 
			
		||||
                break;
 | 
			
		||||
            case pbf_wire_type::fixed64:
 | 
			
		||||
                skip_bytes(8);
 | 
			
		||||
                break;
 | 
			
		||||
            case pbf_wire_type::length_delimited:
 | 
			
		||||
                skip_bytes(get_length());
 | 
			
		||||
                break;
 | 
			
		||||
            case pbf_wire_type::fixed32:
 | 
			
		||||
                skip_bytes(4);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///@{
 | 
			
		||||
    /**
 | 
			
		||||
     * @name Scalar field accessor functions
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "bool" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "bool".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    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;
 | 
			
		||||
        skip_varint(&m_data, m_end);
 | 
			
		||||
        return data[0] != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "enum" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "enum".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int32_t get_enum() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_varint<int32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "int32" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "int32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int32_t get_int32() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_varint<int32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "sint32" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "sint32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int32_t get_sint32() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_svarint<int32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "uint32" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "uint32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    uint32_t get_uint32() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_varint<uint32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "int64" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "int64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int64_t get_int64() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_varint<int64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "sint64" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "sint64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int64_t get_sint64() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_svarint<int64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "uint64" varint field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "uint64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    uint64_t get_uint64() {
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::varint) && "not a varint");
 | 
			
		||||
        return get_varint<uint64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "fixed32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "fixed32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    uint32_t get_fixed32() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed32) && "not a 32-bit fixed");
 | 
			
		||||
        return get_fixed<uint32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "sfixed32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "sfixed32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int32_t get_sfixed32() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed32) && "not a 32-bit fixed");
 | 
			
		||||
        return get_fixed<int32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "fixed64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "fixed64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    uint64_t get_fixed64() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed64) && "not a 64-bit fixed");
 | 
			
		||||
        return get_fixed<uint64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "sfixed64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "sfixed64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    int64_t get_sfixed64() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed64) && "not a 64-bit fixed");
 | 
			
		||||
        return get_fixed<int64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "float" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "float".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    float get_float() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed32) && "not a 32-bit fixed");
 | 
			
		||||
        return get_fixed<float>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "double" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "double".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    double get_double() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::fixed64) && "not a 64-bit fixed");
 | 
			
		||||
        return get_fixed<double>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "bytes", "string", or "message"
 | 
			
		||||
     * field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns A data_view object.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "bytes", "string", or "message".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    data_view get_view() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::length_delimited) && "not of type string, bytes or message");
 | 
			
		||||
        const auto len = get_len_and_skip();
 | 
			
		||||
        return {m_data - len, len};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifndef PROTOZERO_STRICT_API
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "bytes" or "string" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns A pair with a pointer to the data and the length of the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "bytes" or "string".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    std::pair<const char*, pbf_length_type> get_data() {
 | 
			
		||||
        protozero_assert(tag() != 0 && "call next() before accessing field value");
 | 
			
		||||
        protozero_assert(has_wire_type(pbf_wire_type::length_delimited) && "not of type string, bytes or message");
 | 
			
		||||
        const auto len = get_len_and_skip();
 | 
			
		||||
        return {m_data - len, len};
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "bytes" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "bytes".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    std::string get_bytes() {
 | 
			
		||||
        return std::string(get_view());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "string" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "string".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    std::string get_string() {
 | 
			
		||||
        return std::string(get_view());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume and return value of current "message" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "message".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    pbf_reader get_message() {
 | 
			
		||||
        return pbf_reader{get_view()};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///@}
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over bool (int32 varint) values.
 | 
			
		||||
    using const_bool_iterator   = const_varint_iterator< int32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over enum (int32 varint) values.
 | 
			
		||||
    using const_enum_iterator   = const_varint_iterator< int32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over int32 (varint) values.
 | 
			
		||||
    using const_int32_iterator  = const_varint_iterator< int32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over sint32 (varint) values.
 | 
			
		||||
    using const_sint32_iterator = const_svarint_iterator<int32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over uint32 (varint) values.
 | 
			
		||||
    using const_uint32_iterator = const_varint_iterator<uint32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over int64 (varint) values.
 | 
			
		||||
    using const_int64_iterator  = const_varint_iterator< int64_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over sint64 (varint) values.
 | 
			
		||||
    using const_sint64_iterator = const_svarint_iterator<int64_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over uint64 (varint) values.
 | 
			
		||||
    using const_uint64_iterator = const_varint_iterator<uint64_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over fixed32 values.
 | 
			
		||||
    using const_fixed32_iterator = const_fixed_iterator<uint32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over sfixed32 values.
 | 
			
		||||
    using const_sfixed32_iterator = const_fixed_iterator<int32_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over fixed64 values.
 | 
			
		||||
    using const_fixed64_iterator = const_fixed_iterator<uint64_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over sfixed64 values.
 | 
			
		||||
    using const_sfixed64_iterator = const_fixed_iterator<int64_t>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over float values.
 | 
			
		||||
    using const_float_iterator = const_fixed_iterator<float>;
 | 
			
		||||
 | 
			
		||||
    /// Forward iterator for iterating over double values.
 | 
			
		||||
    using const_double_iterator = const_fixed_iterator<double>;
 | 
			
		||||
 | 
			
		||||
    ///@{
 | 
			
		||||
    /**
 | 
			
		||||
     * @name Repeated packed field accessor functions
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed bool" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed bool".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_bool_iterator> get_packed_bool() {
 | 
			
		||||
        return get_packed<pbf_reader::const_bool_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed enum" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed enum".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_enum_iterator> get_packed_enum() {
 | 
			
		||||
        return get_packed<pbf_reader::const_enum_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed int32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed int32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_int32_iterator> get_packed_int32() {
 | 
			
		||||
        return get_packed<pbf_reader::const_int32_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed sint32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed sint32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_sint32_iterator> get_packed_sint32() {
 | 
			
		||||
        return get_packed<pbf_reader::const_sint32_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed uint32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed uint32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_uint32_iterator> get_packed_uint32() {
 | 
			
		||||
        return get_packed<pbf_reader::const_uint32_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed int64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed int64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_int64_iterator> get_packed_int64() {
 | 
			
		||||
        return get_packed<pbf_reader::const_int64_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed sint64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed sint64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_sint64_iterator> get_packed_sint64() {
 | 
			
		||||
        return get_packed<pbf_reader::const_sint64_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed uint64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed uint64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_uint64_iterator> get_packed_uint64() {
 | 
			
		||||
        return get_packed<pbf_reader::const_uint64_iterator>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed fixed32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed fixed32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_fixed32_iterator> get_packed_fixed32() {
 | 
			
		||||
        return packed_fixed<uint32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed sfixed32" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed sfixed32".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_sfixed32_iterator> get_packed_sfixed32() {
 | 
			
		||||
        return packed_fixed<int32_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed fixed64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed fixed64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_fixed64_iterator> get_packed_fixed64() {
 | 
			
		||||
        return packed_fixed<uint64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed sfixed64" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed sfixed64".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_sfixed64_iterator> get_packed_sfixed64() {
 | 
			
		||||
        return packed_fixed<int64_t>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed float" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed float".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_float_iterator> get_packed_float() {
 | 
			
		||||
        return packed_fixed<float>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Consume current "repeated packed double" field.
 | 
			
		||||
     *
 | 
			
		||||
     * @returns a pair of iterators to the beginning and one past the end of
 | 
			
		||||
     *          the data.
 | 
			
		||||
     * @pre There must be a current field (ie. next() must have returned `true`).
 | 
			
		||||
     * @pre The current field must be of type "repeated packed double".
 | 
			
		||||
     * @post The current field was consumed and there is no current field now.
 | 
			
		||||
     */
 | 
			
		||||
    iterator_range<pbf_reader::const_double_iterator> get_packed_double() {
 | 
			
		||||
        return packed_fixed<double>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ///@}
 | 
			
		||||
 | 
			
		||||
}; // class pbf_reader
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Swap two pbf_reader objects.
 | 
			
		||||
 *
 | 
			
		||||
 * @param lhs First object.
 | 
			
		||||
 * @param rhs Second object.
 | 
			
		||||
 */
 | 
			
		||||
inline void swap(pbf_reader& lhs, pbf_reader& rhs) noexcept {
 | 
			
		||||
    lhs.swap(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_PBF_READER_HPP
 | 
			
		||||
							
								
								
									
										1049
									
								
								third_party/protozero/include/protozero/pbf_writer.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1049
									
								
								third_party/protozero/include/protozero/pbf_writer.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										66
									
								
								third_party/protozero/include/protozero/types.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								third_party/protozero/include/protozero/types.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
#ifndef PROTOZERO_TYPES_HPP
 | 
			
		||||
#define PROTOZERO_TYPES_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 types.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains the declaration of low-level types used in the pbf format.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/config.hpp>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The type used for field tags (field numbers).
 | 
			
		||||
 */
 | 
			
		||||
using pbf_tag_type = uint32_t;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The type used to encode type information.
 | 
			
		||||
 * See the table on
 | 
			
		||||
 *    https://developers.google.com/protocol-buffers/docs/encoding
 | 
			
		||||
 */
 | 
			
		||||
enum class pbf_wire_type : uint32_t {
 | 
			
		||||
    varint           = 0, // int32/64, uint32/64, sint32/64, bool, enum
 | 
			
		||||
    fixed64          = 1, // fixed64, sfixed64, double
 | 
			
		||||
    length_delimited = 2, // string, bytes, nested messages, packed repeated fields
 | 
			
		||||
    fixed32          = 5, // fixed32, sfixed32, float
 | 
			
		||||
    unknown          = 99 // used for default setting in this library
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the tag and wire type of the current field in one integer suitable
 | 
			
		||||
 * for comparison with a switch statement.
 | 
			
		||||
 *
 | 
			
		||||
 * See pbf_reader.tag_and_type() for an example how to use this.
 | 
			
		||||
 */
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The type used for length values, such as the length of a field.
 | 
			
		||||
 */
 | 
			
		||||
using pbf_length_type = uint32_t;
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_TYPES_HPP
 | 
			
		||||
							
								
								
									
										188
									
								
								third_party/protozero/include/protozero/varint.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								third_party/protozero/include/protozero/varint.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,188 @@
 | 
			
		||||
#ifndef PROTOZERO_VARINT_HPP
 | 
			
		||||
#define PROTOZERO_VARINT_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 varint.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains low-level varint and zigzag encoding and decoding functions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <protozero/exception.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
 | 
			
		||||
namespace protozero {
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The maximum length of a 64 bit varint.
 | 
			
		||||
 */
 | 
			
		||||
constexpr const int8_t max_varint_length = sizeof(uint64_t) * 8 / 7 + 1;
 | 
			
		||||
 | 
			
		||||
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 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; }
 | 
			
		||||
                throw varint_too_long_exception{};
 | 
			
		||||
            } while (false);
 | 
			
		||||
        } else {
 | 
			
		||||
            unsigned int shift = 0;
 | 
			
		||||
            while (p != iend && *p < 0) {
 | 
			
		||||
                val |= uint64_t(*p++ & 0x7fu) << shift;
 | 
			
		||||
                shift += 7;
 | 
			
		||||
            }
 | 
			
		||||
            if (p == iend) {
 | 
			
		||||
                throw end_of_buffer_exception{};
 | 
			
		||||
            }
 | 
			
		||||
            val |= uint64_t(*p++) << shift;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *data = reinterpret_cast<const char*>(p);
 | 
			
		||||
        return val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
} // end namespace detail
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Decode a 64 bit varint.
 | 
			
		||||
 *
 | 
			
		||||
 * Strong exception guarantee: if there is an exception the data pointer will
 | 
			
		||||
 * not be changed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in,out] data Pointer to pointer to the input data. After the function
 | 
			
		||||
 *        returns this will point to the next data to be read.
 | 
			
		||||
 * @param[in] end Pointer one past the end of the input data.
 | 
			
		||||
 * @returns The decoded integer
 | 
			
		||||
 * @throws varint_too_long_exception if the varint is longer then the maximum
 | 
			
		||||
 *         length that would fit in a 64 bit int. Usually this means your data
 | 
			
		||||
 *         is corrupted or you are trying to read something as a varint that
 | 
			
		||||
 *         isn't.
 | 
			
		||||
 * @throws end_of_buffer_exception if the *end* of the buffer was reached
 | 
			
		||||
 *         before the end of the varint.
 | 
			
		||||
 */
 | 
			
		||||
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)) {
 | 
			
		||||
        const auto val = static_cast<uint64_t>(**data);
 | 
			
		||||
        ++(*data);
 | 
			
		||||
        return val;
 | 
			
		||||
    }
 | 
			
		||||
    // If this varint is more than one byte, defer to complete implementation.
 | 
			
		||||
    return detail::decode_varint_impl(data, end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Skip over a varint.
 | 
			
		||||
 *
 | 
			
		||||
 * Strong exception guarantee: if there is an exception the data pointer will
 | 
			
		||||
 * not be changed.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in,out] data Pointer to pointer to the input data. After the function
 | 
			
		||||
 *        returns this will point to the next data to be read.
 | 
			
		||||
 * @param[in] end Pointer one past the end of the input data.
 | 
			
		||||
 * @throws end_of_buffer_exception if the *end* of the buffer was reached
 | 
			
		||||
 *         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 int8_t* p = begin;
 | 
			
		||||
 | 
			
		||||
    while (p != iend && *p < 0) {
 | 
			
		||||
        ++p;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (p >= begin + max_varint_length) {
 | 
			
		||||
        throw varint_too_long_exception{};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (p == iend) {
 | 
			
		||||
        throw end_of_buffer_exception{};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ++p;
 | 
			
		||||
 | 
			
		||||
    *data = reinterpret_cast<const char*>(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Varint encode a 64 bit integer.
 | 
			
		||||
 *
 | 
			
		||||
 * @tparam T An output iterator type.
 | 
			
		||||
 * @param data Output iterator the varint encoded value will be written to
 | 
			
		||||
 *             byte by byte.
 | 
			
		||||
 * @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.
 | 
			
		||||
 */
 | 
			
		||||
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;
 | 
			
		||||
        ++n;
 | 
			
		||||
    }
 | 
			
		||||
    *data++ = char(value);
 | 
			
		||||
 | 
			
		||||
    return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // end namespace protozero
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_VARINT_HPP
 | 
			
		||||
							
								
								
									
										34
									
								
								third_party/protozero/include/protozero/version.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								third_party/protozero/include/protozero/version.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
			
		||||
#ifndef PROTOZERO_VERSION_HPP
 | 
			
		||||
#define PROTOZERO_VERSION_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 version.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * @brief Contains macros defining the protozero version.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/// The major version number
 | 
			
		||||
#define PROTOZERO_VERSION_MAJOR 1
 | 
			
		||||
 | 
			
		||||
/// The minor version number
 | 
			
		||||
#define PROTOZERO_VERSION_MINOR 6
 | 
			
		||||
 | 
			
		||||
/// The patch number
 | 
			
		||||
#define PROTOZERO_VERSION_PATCH 2
 | 
			
		||||
 | 
			
		||||
/// 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"
 | 
			
		||||
 | 
			
		||||
#endif // PROTOZERO_VERSION_HPP
 | 
			
		||||
							
								
								
									
										116
									
								
								third_party/protozero/test/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								third_party/protozero/test/CMakeLists.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,116 @@
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
#  CMake config
 | 
			
		||||
#
 | 
			
		||||
#  protozero tests
 | 
			
		||||
#
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/catch")
 | 
			
		||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
 | 
			
		||||
 | 
			
		||||
add_subdirectory(unit)
 | 
			
		||||
 | 
			
		||||
set(TEST_DIRS alignment
 | 
			
		||||
              bool
 | 
			
		||||
              bytes
 | 
			
		||||
              complex
 | 
			
		||||
              double
 | 
			
		||||
              enum
 | 
			
		||||
              fixed32
 | 
			
		||||
              fixed64
 | 
			
		||||
              float
 | 
			
		||||
              int32
 | 
			
		||||
              int64
 | 
			
		||||
              message
 | 
			
		||||
              nested
 | 
			
		||||
              repeated
 | 
			
		||||
              repeated_packed_bool
 | 
			
		||||
              repeated_packed_double
 | 
			
		||||
              repeated_packed_enum
 | 
			
		||||
              repeated_packed_fixed32
 | 
			
		||||
              repeated_packed_fixed64
 | 
			
		||||
              repeated_packed_float
 | 
			
		||||
              repeated_packed_int32
 | 
			
		||||
              repeated_packed_int64
 | 
			
		||||
              repeated_packed_sfixed32
 | 
			
		||||
              repeated_packed_sfixed64
 | 
			
		||||
              repeated_packed_sint32
 | 
			
		||||
              repeated_packed_sint64
 | 
			
		||||
              repeated_packed_uint32
 | 
			
		||||
              repeated_packed_uint64
 | 
			
		||||
              rollback
 | 
			
		||||
              sfixed32
 | 
			
		||||
              sfixed64
 | 
			
		||||
              sint32
 | 
			
		||||
              sint64
 | 
			
		||||
              skip
 | 
			
		||||
              string
 | 
			
		||||
              tag_and_type
 | 
			
		||||
              tags
 | 
			
		||||
              uint32
 | 
			
		||||
              uint64
 | 
			
		||||
              vector_tile
 | 
			
		||||
              wrong_type_access)
 | 
			
		||||
 | 
			
		||||
string(REGEX REPLACE "([^;]+)" "t/\\1/reader_test_cases.cpp" _test_sources "${TEST_DIRS}")
 | 
			
		||||
 | 
			
		||||
add_executable(reader_tests reader_tests.cpp ${_test_sources})
 | 
			
		||||
 | 
			
		||||
add_test(NAME reader_tests COMMAND reader_tests)
 | 
			
		||||
 | 
			
		||||
set_tests_properties(reader_tests PROPERTIES WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
 | 
			
		||||
 | 
			
		||||
if(PROTOBUF_FOUND)
 | 
			
		||||
    message(STATUS "Found protobuf libraries: Adding writer tests...")
 | 
			
		||||
 | 
			
		||||
    include_directories(SYSTEM ${PROTOBUF_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
 | 
			
		||||
 | 
			
		||||
    set(PROTOBUF_GENERATE_CPP_APPEND_PATH false)
 | 
			
		||||
 | 
			
		||||
    foreach(_dir IN LISTS TEST_DIRS)
 | 
			
		||||
        set(_full_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/t/${_dir}")
 | 
			
		||||
        if(EXISTS "${_full_src_dir}/writer_test_cases.cpp")
 | 
			
		||||
            message(STATUS "  Adding ${_dir}")
 | 
			
		||||
            set(_full_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/t/${_dir}")
 | 
			
		||||
            set(_proto_file "${_full_src_dir}/${_dir}_testcase.proto")
 | 
			
		||||
            set(_src_file "${_full_bin_dir}/${_dir}_testcase.pb.cc")
 | 
			
		||||
            set(_hdr_file "${_full_bin_dir}/${_dir}_testcase.pb.h")
 | 
			
		||||
 | 
			
		||||
            file(MAKE_DIRECTORY ${_full_bin_dir})
 | 
			
		||||
 | 
			
		||||
            list(APPEND SOURCES     "${_full_src_dir}/writer_test_cases.cpp")
 | 
			
		||||
            list(APPEND PROTO_FILES "${_proto_file}")
 | 
			
		||||
            list(APPEND PROTO_SRCS  "${_src_file}")
 | 
			
		||||
            list(APPEND PROTO_HDRS  "${_hdr_file}")
 | 
			
		||||
 | 
			
		||||
            set_source_files_properties(${_proto_file} ${_hdr_file}
 | 
			
		||||
                                        PROPERTIES GENERATED TRUE)
 | 
			
		||||
 | 
			
		||||
            add_custom_command(
 | 
			
		||||
                OUTPUT ${_src_file} ${_hdr_file}
 | 
			
		||||
                COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
 | 
			
		||||
                ARGS --cpp_out=${_full_bin_dir} -I ${_full_src_dir} ${_proto_file}
 | 
			
		||||
                DEPENDS ${_proto_file}
 | 
			
		||||
                VERBATIM)
 | 
			
		||||
        endif()
 | 
			
		||||
    endforeach()
 | 
			
		||||
 | 
			
		||||
    add_executable(writer_tests writer_tests.cpp ${SOURCES} ${PROTO_SRCS} ${PROTO_HDRS})
 | 
			
		||||
 | 
			
		||||
    target_link_libraries(writer_tests ${PROTOBUF_LITE_LIBRARY})
 | 
			
		||||
 | 
			
		||||
    if(NOT MSVC)
 | 
			
		||||
        set_target_properties(writer_tests PROPERTIES COMPILE_FLAGS "-pthread")
 | 
			
		||||
        if(NOT APPLE)
 | 
			
		||||
            set_target_properties(writer_tests PROPERTIES LINK_FLAGS "-pthread")
 | 
			
		||||
        endif()
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    add_test(NAME writer_tests COMMAND writer_tests)
 | 
			
		||||
else()
 | 
			
		||||
    message(STATUS "Protobuf libraries not found: Disabling writer tests.")
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#-----------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										52
									
								
								third_party/protozero/test/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								third_party/protozero/test/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
			
		||||
 | 
			
		||||
# Tests
 | 
			
		||||
 | 
			
		||||
Tests are using the [Catch Unit Test Framework](https://github.com/philsquared/Catch).
 | 
			
		||||
 | 
			
		||||
## Organization of the unit tests
 | 
			
		||||
 | 
			
		||||
Unit tests test low-level functions of the library. They are in the `unit`
 | 
			
		||||
directory.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Organization of the reader/writer test cases
 | 
			
		||||
 | 
			
		||||
The hart of the tests are the reader/writer tests checking all aspects of
 | 
			
		||||
decoding and encoding protobuf files.
 | 
			
		||||
 | 
			
		||||
Each test case is in its own directory under the `t` directory. Each directory
 | 
			
		||||
contains (some of) the following files:
 | 
			
		||||
 | 
			
		||||
* `reader_test_cases.cpp`: The C++ source code that runs the reader tests.
 | 
			
		||||
* `writer_test_cases.cpp`: The C++ source code that runs the writer tests.
 | 
			
		||||
* `data-*.pbf`: PBF data files used by the tests.
 | 
			
		||||
* `testcase.proto`: Protobuf file describing the format of the data files.
 | 
			
		||||
* `testcase.cpp`: C++ file for creating the data files.
 | 
			
		||||
 | 
			
		||||
### Reader tests
 | 
			
		||||
 | 
			
		||||
The CMake config finds all the `reader_test_cases.cpp` files and compiles them.
 | 
			
		||||
Together with the `reader_tests.cpp` file they make up the `reader_tests`
 | 
			
		||||
executable which can be called to execute all the reader tests.
 | 
			
		||||
 | 
			
		||||
### Extra writer tests
 | 
			
		||||
 | 
			
		||||
The CMake config finds all the `writer_test_cases.cpp` files and compiles them.
 | 
			
		||||
Together with the `writer_tests.cpp` file they make up the `writer_tests`
 | 
			
		||||
executable which can be called to execute all the writer tests.
 | 
			
		||||
 | 
			
		||||
The writer tests need the Google protobuf library to work.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Creating test data from scratch
 | 
			
		||||
 | 
			
		||||
Most tests use test data stored in PBF format in their directory. The files
 | 
			
		||||
have the suffix `.pbf`. Most of those files have been generated from the
 | 
			
		||||
provided `testcase.proto` and `testcase.cpp` files.
 | 
			
		||||
 | 
			
		||||
Usually you do not have to do this, but if you want to re-generate the PBF
 | 
			
		||||
data files, you can do so:
 | 
			
		||||
 | 
			
		||||
    cd test
 | 
			
		||||
    ./create_pbf_test_data.sh
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11678
									
								
								third_party/protozero/test/catch/catch.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11678
									
								
								third_party/protozero/test/catch/catch.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								third_party/protozero/test/create_pbf_test_data.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										28
									
								
								third_party/protozero/test/create_pbf_test_data.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
#  create_pbf_test_data.sh [TESTCASE]
 | 
			
		||||
#
 | 
			
		||||
#  This script creates the test data for the given test case in protobuf format
 | 
			
		||||
#  using the testcase.proto description and the testcase.cpp code.
 | 
			
		||||
#
 | 
			
		||||
#  If called without a test case it will iterate over all test cases generating
 | 
			
		||||
#  all data.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
if [ -z "$1" ]; then
 | 
			
		||||
    for dir in t/*; do
 | 
			
		||||
        $0 $dir
 | 
			
		||||
    done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "Generating $1..."
 | 
			
		||||
cd $1
 | 
			
		||||
if [ -f testcase.proto ]; then
 | 
			
		||||
    protoc --cpp_out=. testcase.proto
 | 
			
		||||
    $CXX -std=c++11 -I../../include -o testcase testcase.cpp testcase.pb.cc -lprotobuf-lite -pthread
 | 
			
		||||
    ./testcase
 | 
			
		||||
fi
 | 
			
		||||
cd ../..
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										296
									
								
								third_party/protozero/test/include/packed_access.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								third_party/protozero/test/include/packed_access.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,296 @@
 | 
			
		||||
// NOLINT(llvm-header-guard)
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
using packed_field_type = PROTOZERO_TEST_CONCAT(protozero::packed_field_, PBF_TYPE);
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read repeated packed field: " PBF_TYPE_NAME) {
 | 
			
		||||
    // 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
 | 
			
		||||
    // is aligned before that, in at least one of these cases the ints will
 | 
			
		||||
    // not be aligned properly. So we test that even in that case the ints
 | 
			
		||||
    // will be extracted properly.
 | 
			
		||||
 | 
			
		||||
    for (std::string::size_type n = 0; n < 2; ++n) {
 | 
			
		||||
        std::string abuffer;
 | 
			
		||||
        abuffer.reserve(1000);
 | 
			
		||||
        abuffer.append(n, '\0');
 | 
			
		||||
 | 
			
		||||
        SECTION("empty") {
 | 
			
		||||
            abuffer.append(load_data("repeated_packed_" PBF_TYPE_NAME "/data-empty"));
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("one") {
 | 
			
		||||
            abuffer.append(load_data("repeated_packed_" PBF_TYPE_NAME "/data-one"));
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            const auto it_range = item.GET_TYPE();
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
 | 
			
		||||
            REQUIRE(it_range.begin() != it_range.end());
 | 
			
		||||
            REQUIRE(*it_range.begin() == 17);
 | 
			
		||||
            REQUIRE(std::next(it_range.begin()) == it_range.end());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("many") {
 | 
			
		||||
            abuffer.append(load_data("repeated_packed_" PBF_TYPE_NAME "/data-many"));
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            const auto it_range = item.GET_TYPE();
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
 | 
			
		||||
            auto it = it_range.begin();
 | 
			
		||||
            REQUIRE(it != it_range.end());
 | 
			
		||||
            REQUIRE(*it++ ==   17);
 | 
			
		||||
            REQUIRE(*it++ ==  200);
 | 
			
		||||
            REQUIRE(*it++ ==    0);
 | 
			
		||||
            REQUIRE(*it++ ==    1);
 | 
			
		||||
            REQUIRE(*it++ == std::numeric_limits<cpp_type>::max());
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
            REQUIRE(*it++ == -200);
 | 
			
		||||
            REQUIRE(*it++ ==   -1);
 | 
			
		||||
            REQUIRE(*it++ == std::numeric_limits<cpp_type>::min());
 | 
			
		||||
#endif
 | 
			
		||||
            REQUIRE(it == it_range.end());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("swap iterator range") {
 | 
			
		||||
            abuffer.append(load_data("repeated_packed_" PBF_TYPE_NAME "/data-many"));
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            auto it_range1 = item.GET_TYPE();
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
 | 
			
		||||
            decltype(it_range1) it_range;
 | 
			
		||||
            using std::swap;
 | 
			
		||||
            swap(it_range, it_range1);
 | 
			
		||||
 | 
			
		||||
            auto it = it_range.begin();
 | 
			
		||||
            REQUIRE(it != it_range.end());
 | 
			
		||||
            REQUIRE(*it++ ==   17);
 | 
			
		||||
            REQUIRE(*it++ ==  200);
 | 
			
		||||
            REQUIRE(*it++ ==    0);
 | 
			
		||||
            REQUIRE(*it++ ==    1);
 | 
			
		||||
            REQUIRE(*it++ == std::numeric_limits<cpp_type>::max());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("end_of_buffer") {
 | 
			
		||||
            abuffer.append(load_data("repeated_packed_" PBF_TYPE_NAME "/data-many"));
 | 
			
		||||
 | 
			
		||||
            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&);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write repeated packed field: " PBF_TYPE_NAME) {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("empty") {
 | 
			
		||||
        cpp_type 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 };
 | 
			
		||||
        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[] = {
 | 
			
		||||
               17
 | 
			
		||||
            , 200
 | 
			
		||||
            ,   0
 | 
			
		||||
            ,   1
 | 
			
		||||
            ,std::numeric_limits<cpp_type>::max()
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
            ,-200
 | 
			
		||||
            ,  -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"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write repeated packed field using packed field: " PBF_TYPE_NAME) {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("empty - should do rollback") {
 | 
			
		||||
        {
 | 
			
		||||
            packed_field_type field{pw, 1};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-empty"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("one") {
 | 
			
		||||
        {
 | 
			
		||||
            packed_field_type field{pw, 1};
 | 
			
		||||
            field.add_element(cpp_type(17));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-one"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("many") {
 | 
			
		||||
        {
 | 
			
		||||
            packed_field_type field{pw, 1};
 | 
			
		||||
            field.add_element(cpp_type(  17));
 | 
			
		||||
            field.add_element(cpp_type( 200));
 | 
			
		||||
            field.add_element(cpp_type(   0));
 | 
			
		||||
            field.add_element(cpp_type(   1));
 | 
			
		||||
            field.add_element(std::numeric_limits<cpp_type>::max());
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
            field.add_element(cpp_type(-200));
 | 
			
		||||
            field.add_element(cpp_type(  -1));
 | 
			
		||||
            field.add_element(std::numeric_limits<cpp_type>::min());
 | 
			
		||||
#endif
 | 
			
		||||
            REQUIRE(field.valid());
 | 
			
		||||
            SECTION("with commit") {
 | 
			
		||||
                field.commit();
 | 
			
		||||
                REQUIRE_FALSE(field.valid());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-many"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("move repeated packed field: " PBF_TYPE_NAME) {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("move rvalue") {
 | 
			
		||||
        packed_field_type field;
 | 
			
		||||
        REQUIRE_FALSE(field.valid());
 | 
			
		||||
        field = packed_field_type{pw, 1};
 | 
			
		||||
        REQUIRE(field.valid());
 | 
			
		||||
        field.add_element(cpp_type(17));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("explicit move") {
 | 
			
		||||
        packed_field_type field2{pw, 1};
 | 
			
		||||
        packed_field_type field;
 | 
			
		||||
 | 
			
		||||
        REQUIRE(field2.valid());
 | 
			
		||||
        REQUIRE_FALSE(field.valid());
 | 
			
		||||
 | 
			
		||||
        field = std::move(field2);
 | 
			
		||||
 | 
			
		||||
        REQUIRE_FALSE(field2.valid()); // NOLINT(hicpp-invalid-access-moved, bugprone-use-after-move)
 | 
			
		||||
        REQUIRE(field.valid());
 | 
			
		||||
 | 
			
		||||
        field.add_element(cpp_type(17));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("move constructor") {
 | 
			
		||||
        packed_field_type field2{pw, 1};
 | 
			
		||||
        REQUIRE(field2.valid());
 | 
			
		||||
 | 
			
		||||
        packed_field_type field{std::move(field2)};
 | 
			
		||||
        REQUIRE(field.valid());
 | 
			
		||||
        REQUIRE_FALSE(field2.valid()); // NOLINT(hicpp-invalid-access-moved, bugprone-use-after-move)
 | 
			
		||||
 | 
			
		||||
        field.add_element(cpp_type(17));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("swap") {
 | 
			
		||||
        packed_field_type field;
 | 
			
		||||
        packed_field_type field2{pw, 1};
 | 
			
		||||
 | 
			
		||||
        REQUIRE_FALSE(field.valid());
 | 
			
		||||
        REQUIRE(field2.valid());
 | 
			
		||||
 | 
			
		||||
        using std::swap;
 | 
			
		||||
        swap(field, field2);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(field.valid());
 | 
			
		||||
        REQUIRE_FALSE(field2.valid());
 | 
			
		||||
 | 
			
		||||
        field.add_element(cpp_type(17));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    REQUIRE(buffer == load_data("repeated_packed_" PBF_TYPE_NAME "/data-one"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write from different types of iterators: " PBF_TYPE_NAME) {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("from uint16_t") {
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
        const  int16_t data[] = { 1, 4, 9, 16, 25 };
 | 
			
		||||
#else
 | 
			
		||||
        const uint16_t data[] = { 1, 4, 9, 16, 25 };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        pw.ADD_TYPE(1, std::begin(data), std::end(data));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("from string") {
 | 
			
		||||
        std::string data{"1 4 9 16 25"};
 | 
			
		||||
        std::stringstream sdata{data};
 | 
			
		||||
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
        using test_type =  int32_t;
 | 
			
		||||
#else
 | 
			
		||||
        using test_type = uint32_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        std::istream_iterator<test_type> eod;
 | 
			
		||||
        std::istream_iterator<test_type> it(sdata);
 | 
			
		||||
 | 
			
		||||
        pw.ADD_TYPE(1, it, eod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    auto it_range = item.GET_TYPE();
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
    REQUIRE_FALSE(it_range.empty());
 | 
			
		||||
    REQUIRE(std::distance(it_range.begin(), it_range.end()) == 5);
 | 
			
		||||
    REQUIRE(it_range.size() == 5);
 | 
			
		||||
 | 
			
		||||
    REQUIRE(it_range.front() ==  1); it_range.drop_front();
 | 
			
		||||
    REQUIRE(it_range.front() ==  4); it_range.drop_front();
 | 
			
		||||
    REQUIRE(std::distance(it_range.begin(), it_range.end()) == 3);
 | 
			
		||||
    REQUIRE(it_range.size() == 3);
 | 
			
		||||
    REQUIRE(it_range.front() ==  9); it_range.drop_front();
 | 
			
		||||
    REQUIRE(it_range.front() == 16); it_range.drop_front();
 | 
			
		||||
    REQUIRE(it_range.front() == 25); it_range.drop_front();
 | 
			
		||||
    REQUIRE(it_range.empty());
 | 
			
		||||
    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&);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										129
									
								
								third_party/protozero/test/include/scalar_access.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								third_party/protozero/test/include/scalar_access.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
			
		||||
// NOLINT(llvm-header-guard)
 | 
			
		||||
 | 
			
		||||
#define PBF_TYPE_NAME PROTOZERO_TEST_STRING(PBF_TYPE)
 | 
			
		||||
#define GET_TYPE PROTOZERO_TEST_CONCAT(get_, PBF_TYPE)
 | 
			
		||||
#define ADD_TYPE PROTOZERO_TEST_CONCAT(add_, PBF_TYPE)
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read field: " PBF_TYPE_NAME) {
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-zero");
 | 
			
		||||
 | 
			
		||||
        protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
        REQUIRE(item.next());
 | 
			
		||||
        REQUIRE(item.GET_TYPE() == 0);
 | 
			
		||||
        REQUIRE_FALSE(item.next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-pos");
 | 
			
		||||
 | 
			
		||||
        protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
        REQUIRE(item.next());
 | 
			
		||||
        REQUIRE(item.GET_TYPE() == 1);
 | 
			
		||||
        REQUIRE_FALSE(item.next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("pos200") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-pos200");
 | 
			
		||||
 | 
			
		||||
        protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
        REQUIRE(item.next());
 | 
			
		||||
        REQUIRE(item.GET_TYPE() == 200);
 | 
			
		||||
        REQUIRE_FALSE(item.next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("max") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-max");
 | 
			
		||||
 | 
			
		||||
        protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
        REQUIRE(item.next());
 | 
			
		||||
        REQUIRE(item.GET_TYPE() == std::numeric_limits<cpp_type>::max());
 | 
			
		||||
        REQUIRE_FALSE(item.next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        if (std::is_signed<cpp_type>::value) {
 | 
			
		||||
            const std::string buffer = load_data(PBF_TYPE_NAME "/data-neg");
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.GET_TYPE() == -1);
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("neg200") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-neg200");
 | 
			
		||||
 | 
			
		||||
        protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
        REQUIRE(item.next());
 | 
			
		||||
        REQUIRE(item.GET_TYPE() == -200);
 | 
			
		||||
        REQUIRE_FALSE(item.next());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("min") {
 | 
			
		||||
        if (std::is_signed<cpp_type>::value) {
 | 
			
		||||
            const std::string buffer = load_data(PBF_TYPE_NAME "/data-min");
 | 
			
		||||
 | 
			
		||||
            protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.GET_TYPE() == std::numeric_limits<cpp_type>::min());
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    SECTION("end_of_buffer") {
 | 
			
		||||
        const std::string buffer = load_data(PBF_TYPE_NAME "/data-max");
 | 
			
		||||
 | 
			
		||||
        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&);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write field: " PBF_TYPE_NAME) {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw(buffer);
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.ADD_TYPE(1, 0);
 | 
			
		||||
        REQUIRE(buffer == load_data(PBF_TYPE_NAME "/data-zero"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        pw.ADD_TYPE(1, 1);
 | 
			
		||||
        REQUIRE(buffer == load_data(PBF_TYPE_NAME "/data-pos"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("max") {
 | 
			
		||||
        pw.ADD_TYPE(1, std::numeric_limits<cpp_type>::max());
 | 
			
		||||
        REQUIRE(buffer == load_data(PBF_TYPE_NAME "/data-max"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if PBF_TYPE_IS_SIGNED
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        pw.ADD_TYPE(1, -1);
 | 
			
		||||
        REQUIRE(buffer == load_data(PBF_TYPE_NAME "/data-neg"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("min") {
 | 
			
		||||
        if (std::is_signed<cpp_type>::value) {
 | 
			
		||||
            pw.ADD_TYPE(1, std::numeric_limits<cpp_type>::min());
 | 
			
		||||
            REQUIRE(buffer == load_data(PBF_TYPE_NAME "/data-min"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								third_party/protozero/test/include/test.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								third_party/protozero/test/include/test.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#ifndef TEST_HPP
 | 
			
		||||
#define TEST_HPP
 | 
			
		||||
 | 
			
		||||
#include <catch.hpp>
 | 
			
		||||
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
// Define protozero_assert() to throw this error. This allows the tests to
 | 
			
		||||
// check that the assert fails.
 | 
			
		||||
struct assert_error : public std::runtime_error {
 | 
			
		||||
    explicit assert_error(const char* what_arg) : std::runtime_error(what_arg) {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
#define protozero_assert(x) if (!(x)) { throw assert_error{#x}; }
 | 
			
		||||
 | 
			
		||||
#include <protozero/pbf_builder.hpp>
 | 
			
		||||
#include <protozero/pbf_message.hpp>
 | 
			
		||||
#include <protozero/pbf_reader.hpp>
 | 
			
		||||
#include <protozero/pbf_writer.hpp>
 | 
			
		||||
 | 
			
		||||
extern std::string load_data(const std::string& filename);
 | 
			
		||||
 | 
			
		||||
#define PROTOZERO_TEST_CONCAT2(x, y) x##y
 | 
			
		||||
#define PROTOZERO_TEST_CONCAT(x, y) PROTOZERO_TEST_CONCAT2(x, y)
 | 
			
		||||
 | 
			
		||||
#define PROTOZERO_TEST_STRING2(s) #s
 | 
			
		||||
#define PROTOZERO_TEST_STRING(s) PROTOZERO_TEST_STRING2(s)
 | 
			
		||||
 | 
			
		||||
#endif // TEST_HPP
 | 
			
		||||
							
								
								
									
										21
									
								
								third_party/protozero/test/include/testcase.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								third_party/protozero/test/include/testcase.hpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
#ifndef TESTCASE_HPP
 | 
			
		||||
#define TESTCASE_HPP
 | 
			
		||||
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <limits>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
std::string write_to_file(const T& msg, const char* filename) {
 | 
			
		||||
    std::string out;
 | 
			
		||||
 | 
			
		||||
    msg.SerializeToString(&out);
 | 
			
		||||
    std::ofstream d{filename, std::ios_base::out|std::ios_base::binary};
 | 
			
		||||
    assert(d.is_open());
 | 
			
		||||
    d << out;
 | 
			
		||||
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TESTCASE_HPP
 | 
			
		||||
							
								
								
									
										30
									
								
								third_party/protozero/test/reader_tests.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								third_party/protozero/test/reader_tests.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#define CATCH_CONFIG_MAIN
 | 
			
		||||
#include <test.hpp> // IWYU pragma: keep
 | 
			
		||||
 | 
			
		||||
std::string load_data(const std::string& filename) {
 | 
			
		||||
    const char* tests_dir = std::getenv("TESTS_DIR");
 | 
			
		||||
    if (tests_dir == nullptr) {
 | 
			
		||||
        tests_dir = "test";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string fullname{tests_dir};
 | 
			
		||||
    fullname += "/t/";
 | 
			
		||||
    fullname += filename;
 | 
			
		||||
    fullname += ".pbf";
 | 
			
		||||
 | 
			
		||||
    std::ifstream stream{fullname, std::ios_base::in | std::ios_base::binary};
 | 
			
		||||
    if (!stream.is_open()) {
 | 
			
		||||
        throw std::runtime_error{"could not open: '" + filename + "'"};
 | 
			
		||||
    }
 | 
			
		||||
    std::string buffer{std::istreambuf_iterator<char>(stream.rdbuf()),
 | 
			
		||||
                       std::istreambuf_iterator<char>()};
 | 
			
		||||
    stream.close();
 | 
			
		||||
 | 
			
		||||
    return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										122
									
								
								third_party/protozero/test/t/alignment/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								third_party/protozero/test/t/alignment/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,122 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
// is aligned before that, in at least one of these cases the int32 will
 | 
			
		||||
// not be aligned properly. So we test that even in that case the int32
 | 
			
		||||
// will be extracted properly.
 | 
			
		||||
 | 
			
		||||
TEST_CASE("check alignment issues for fixed32 field") {
 | 
			
		||||
    for (std::string::size_type n = 0; n < 2; ++n) {
 | 
			
		||||
 | 
			
		||||
        std::string abuffer;
 | 
			
		||||
        abuffer.reserve(1000);
 | 
			
		||||
        abuffer.append(n, '\0');
 | 
			
		||||
 | 
			
		||||
        SECTION("zero") {
 | 
			
		||||
            abuffer.append(load_data("fixed32/data-zero"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed32() == 0UL);
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("positive") {
 | 
			
		||||
            abuffer.append(load_data("fixed32/data-pos"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed32() == 1UL);
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("max") {
 | 
			
		||||
            abuffer.append(load_data("fixed32/data-max"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed32() == std::numeric_limits<uint32_t>::max());
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("end_of_buffer") {
 | 
			
		||||
            abuffer.append(load_data("fixed32/data-pos"));
 | 
			
		||||
 | 
			
		||||
            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&);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("assert detecting tag==0") {
 | 
			
		||||
            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(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed32() == 0UL);
 | 
			
		||||
            REQUIRE_THROWS(item.get_fixed32());
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("skip") {
 | 
			
		||||
            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(item.next());
 | 
			
		||||
            item.skip();
 | 
			
		||||
            REQUIRE_THROWS(item.skip());
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("check alignment issues for fixed64 field") {
 | 
			
		||||
    for (std::string::size_type n = 0; n < 2; ++n) {
 | 
			
		||||
        std::string abuffer;
 | 
			
		||||
        abuffer.reserve(1000);
 | 
			
		||||
        abuffer.append(n, '\0');
 | 
			
		||||
 | 
			
		||||
        SECTION("zero") {
 | 
			
		||||
            abuffer.append(load_data("fixed64/data-zero"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed64() == 0ULL);
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("positive") {
 | 
			
		||||
            abuffer.append(load_data("fixed64/data-pos"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed64() == 1ULL);
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("max") {
 | 
			
		||||
            abuffer.append(load_data("fixed64/data-max"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_fixed64() == std::numeric_limits<uint64_t>::max());
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("end_of_buffer") {
 | 
			
		||||
            abuffer.append(load_data("fixed64/data-pos"));
 | 
			
		||||
 | 
			
		||||
            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&);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								third_party/protozero/test/t/bool/bool_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								third_party/protozero/test/t/bool/bool_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestBoolean;
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    // this should be bool, but we are using uint32
 | 
			
		||||
    // to be able to encode values other than 0 (false)
 | 
			
		||||
    // and 1 (true)
 | 
			
		||||
    required uint32 b = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/bool/data-also-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/bool/data-also-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/bool/data-false.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/bool/data-false.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								third_party/protozero/test/t/bool/data-still-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/bool/data-still-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<08>
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/bool/data-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/bool/data-true.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										141
									
								
								third_party/protozero/test/t/bool/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								third_party/protozero/test/t/bool/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
namespace TestBoolean {
 | 
			
		||||
 | 
			
		||||
enum class Test : protozero::pbf_tag_type {
 | 
			
		||||
    required_bool_b = 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // end namespace TestBoolean
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_reader: false") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-false");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE_FALSE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_reader: true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_reader: also true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-also-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next(1));
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_reader: still true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-still-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next(1));
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_message: false") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-false");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestBoolean::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE_FALSE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_message: true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestBoolean::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_message: also true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-also-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestBoolean::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next(TestBoolean::Test::required_bool_b));
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bool field using pbf_message: still true") {
 | 
			
		||||
    const std::string buffer = load_data("bool/data-still-true");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestBoolean::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next(TestBoolean::Test::required_bool_b));
 | 
			
		||||
    REQUIRE(item.get_bool());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bool field using pbf_writer") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("false") {
 | 
			
		||||
        pw.add_bool(1, false);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-false"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("true") {
 | 
			
		||||
        pw.add_bool(1, true);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-true"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bool field using pbf_builder") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<TestBoolean::Test> pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("false") {
 | 
			
		||||
        pw.add_bool(TestBoolean::Test::required_bool_b, false);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-false"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("true") {
 | 
			
		||||
        pw.add_bool(TestBoolean::Test::required_bool_b, true);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-true"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bool field using moved pbf_builder") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<TestBoolean::Test> pw2{buffer};
 | 
			
		||||
    REQUIRE(pw2.valid());
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
    SECTION("false") {
 | 
			
		||||
        pw.add_bool(TestBoolean::Test::required_bool_b, false);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-false"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("true") {
 | 
			
		||||
        pw.add_bool(TestBoolean::Test::required_bool_b, true);
 | 
			
		||||
        REQUIRE(buffer == load_data("bool/data-true"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								third_party/protozero/test/t/bool/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								third_party/protozero/test/t/bool/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestBoolean::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_b(0);
 | 
			
		||||
    write_to_file(msg, "data-false.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_b(1);
 | 
			
		||||
    write_to_file(msg, "data-true.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_b(2);
 | 
			
		||||
    write_to_file(msg, "data-also-true.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_b(2000);
 | 
			
		||||
    write_to_file(msg, "data-still-true.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								third_party/protozero/test/t/bool/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								third_party/protozero/test/t/bool/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <test.hpp> // IWYU pragma: keep
 | 
			
		||||
 | 
			
		||||
#include "t/bool/bool_testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bool field and check with libprotobuf") {
 | 
			
		||||
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    TestBoolean::Test msg;
 | 
			
		||||
 | 
			
		||||
    SECTION("false") {
 | 
			
		||||
        pw.add_bool(1, false);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE_FALSE(msg.b());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("true") {
 | 
			
		||||
        pw.add_bool(1, true);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.b());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								third_party/protozero/test/t/bytes/bytes_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								third_party/protozero/test/t/bytes/bytes_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestBytes;
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    required bytes s = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								third_party/protozero/test/t/bytes/data-binary.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								third_party/protozero/test/t/bytes/data-binary.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/bytes/data-empty.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/bytes/data-empty.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								third_party/protozero/test/t/bytes/data-one.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								third_party/protozero/test/t/bytes/data-one.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
 | 
			
		||||
x
 | 
			
		||||
							
								
								
									
										2
									
								
								third_party/protozero/test/t/bytes/data-string.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								third_party/protozero/test/t/bytes/data-string.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
 | 
			
		||||
foobar
 | 
			
		||||
							
								
								
									
										139
									
								
								third_party/protozero/test/t/bytes/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								third_party/protozero/test/t/bytes/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,139 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bytes field: empty") {
 | 
			
		||||
    const std::string buffer = load_data("bytes/data-empty");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_bytes().empty());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bytes field: one") {
 | 
			
		||||
    const std::string buffer = load_data("bytes/data-one");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_bytes() == "x");
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bytes field: string") {
 | 
			
		||||
    const std::string buffer = load_data("bytes/data-string");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_bytes() == "foobar");
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bytes field: binary") {
 | 
			
		||||
    const std::string buffer = load_data("bytes/data-binary");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    const std::string data = item.get_bytes();
 | 
			
		||||
    REQUIRE(data.size() == 3);
 | 
			
		||||
    REQUIRE(data[0] == char(1));
 | 
			
		||||
    REQUIRE(data[1] == char(2));
 | 
			
		||||
    REQUIRE(data[2] == char(3));
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read bytes field: end of buffer") {
 | 
			
		||||
    const std::string buffer = load_data("bytes/data-binary");
 | 
			
		||||
 | 
			
		||||
    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&);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bytes field") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("empty") {
 | 
			
		||||
        pw.add_string(1, "");
 | 
			
		||||
        REQUIRE(buffer == load_data("bytes/data-empty"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("one") {
 | 
			
		||||
        pw.add_string(1, "x");
 | 
			
		||||
        REQUIRE(buffer == load_data("bytes/data-one"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("string") {
 | 
			
		||||
        pw.add_string(1, "foobar");
 | 
			
		||||
        REQUIRE(buffer == load_data("bytes/data-string"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("binary") {
 | 
			
		||||
        std::string data;
 | 
			
		||||
        data.append(1, char(1));
 | 
			
		||||
        data.append(1, char(2));
 | 
			
		||||
        data.append(1, char(3));
 | 
			
		||||
 | 
			
		||||
        pw.add_string(1, data);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(buffer == load_data("bytes/data-binary"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bytes field using vectored approach") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("using two strings") {
 | 
			
		||||
        std::string d1{"foo"};
 | 
			
		||||
        std::string d2{"bar"};
 | 
			
		||||
 | 
			
		||||
        pw.add_bytes_vectored(1, d1, d2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("using a string and a dataview") {
 | 
			
		||||
        std::string d1{"foo"};
 | 
			
		||||
        std::string d2{"bar"};
 | 
			
		||||
        protozero::data_view dv{d2};
 | 
			
		||||
 | 
			
		||||
        pw.add_bytes_vectored(1, d1, dv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("using three strings") {
 | 
			
		||||
        std::string d1{"foo"};
 | 
			
		||||
        std::string d2{"ba"};
 | 
			
		||||
        std::string d3{"r"};
 | 
			
		||||
 | 
			
		||||
        pw.add_bytes_vectored(1, d1, d2, d3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("with empty string") {
 | 
			
		||||
        std::string d1{"foo"};
 | 
			
		||||
        std::string d2{};
 | 
			
		||||
        std::string d3{"bar"};
 | 
			
		||||
 | 
			
		||||
        pw.add_bytes_vectored(1, d1, d2, d3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    REQUIRE(buffer == load_data("bytes/data-string"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bytes field using vectored approach with builder") {
 | 
			
		||||
    enum class foo : protozero::pbf_tag_type { bar = 1 };
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<foo> pw{buffer};
 | 
			
		||||
 | 
			
		||||
    const std::string d1{"foo"};
 | 
			
		||||
    const std::string d2{"bar"};
 | 
			
		||||
 | 
			
		||||
    pw.add_bytes_vectored(foo::bar, d1, d2);
 | 
			
		||||
 | 
			
		||||
    REQUIRE(buffer == load_data("bytes/data-string"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								third_party/protozero/test/t/bytes/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								third_party/protozero/test/t/bytes/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestBytes::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_s("");
 | 
			
		||||
    write_to_file(msg, "data-empty.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_s("x");
 | 
			
		||||
    write_to_file(msg, "data-one.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_s("foobar");
 | 
			
		||||
    write_to_file(msg, "data-string.pbf");
 | 
			
		||||
 | 
			
		||||
    std::string data;
 | 
			
		||||
    data.append(1, char(1));
 | 
			
		||||
    data.append(1, char(2));
 | 
			
		||||
    data.append(1, char(3));
 | 
			
		||||
    msg.set_s(data);
 | 
			
		||||
    write_to_file(msg, "data-binary.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								third_party/protozero/test/t/bytes/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								third_party/protozero/test/t/bytes/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#include "t/bytes/bytes_testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write bytes field and check with libprotobuf") {
 | 
			
		||||
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    TestBytes::Test msg;
 | 
			
		||||
 | 
			
		||||
    SECTION("empty") {
 | 
			
		||||
        pw.add_string(1, "");
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.s().empty());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("one") {
 | 
			
		||||
        pw.add_string(1, "x");
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.s() == "x");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("string") {
 | 
			
		||||
        pw.add_string(1, "foobar");
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.s() == "foobar");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("binary") {
 | 
			
		||||
        std::string data;
 | 
			
		||||
        data.append(1, char(1));
 | 
			
		||||
        data.append(1, char(2));
 | 
			
		||||
        data.append(1, char(3));
 | 
			
		||||
 | 
			
		||||
        pw.add_string(1, data);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.s().size() == 3);
 | 
			
		||||
        REQUIRE(msg.s()[1] == char(2));
 | 
			
		||||
        REQUIRE(msg.s()[2] == char(3));
 | 
			
		||||
        REQUIRE(msg.s()[2] == char(3));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-all.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-all.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-minimal.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-minimal.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-some.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/complex/data-some.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										686
									
								
								third_party/protozero/test/t/complex/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										686
									
								
								third_party/protozero/test/t/complex/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,686 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
namespace TestComplex {
 | 
			
		||||
 | 
			
		||||
enum class Test : protozero::pbf_tag_type {
 | 
			
		||||
    required_fixed32_f      = 1,
 | 
			
		||||
    optional_int64_i        = 2,
 | 
			
		||||
    optional_int64_j        = 3,
 | 
			
		||||
    required_Sub_submessage = 5,
 | 
			
		||||
    optional_string_s       = 8,
 | 
			
		||||
    repeated_uint32_u       = 4,
 | 
			
		||||
    packed_sint32_d         = 7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class Sub : protozero::pbf_tag_type {
 | 
			
		||||
    required_string_s = 1
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace TestComplex
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_reader: minimal") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-minimal");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case 1: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_reader: some") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-some");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item2{buffer};
 | 
			
		||||
    protozero::pbf_reader item;
 | 
			
		||||
    using std::swap;
 | 
			
		||||
    swap(item, item2);
 | 
			
		||||
 | 
			
		||||
    uint32_t sum_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 4: {
 | 
			
		||||
                sum_of_u += item.get_uint32();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(sum_of_u == 66);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_reader: all") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-all");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
                int32_t sum = 0;
 | 
			
		||||
                for (auto val : pi) {
 | 
			
		||||
                    sum += val;
 | 
			
		||||
                }
 | 
			
		||||
                REQUIRE(sum == 5);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 8: {
 | 
			
		||||
                REQUIRE(item.get_string() == "optionalstring");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(number_of_u == 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_reader: skip everything") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-all");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case 1:
 | 
			
		||||
            case 2:
 | 
			
		||||
            case 3:
 | 
			
		||||
            case 4:
 | 
			
		||||
            case 5:
 | 
			
		||||
            case 7:
 | 
			
		||||
            case 8:
 | 
			
		||||
                item.skip();
 | 
			
		||||
                break;
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_message: minimal") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-minimal");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestComplex::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case TestComplex::Test::required_fixed32_f: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::required_Sub_submessage: {
 | 
			
		||||
                protozero::pbf_message<TestComplex::Sub> subitem{item.get_message()};
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_message: some") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-some");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestComplex::Test> item2{buffer};
 | 
			
		||||
    protozero::pbf_message<TestComplex::Test> item;
 | 
			
		||||
    using std::swap;
 | 
			
		||||
    swap(item, item2);
 | 
			
		||||
 | 
			
		||||
    uint32_t sum_of_u = 0;
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case TestComplex::Test::required_fixed32_f: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::optional_int64_i: {
 | 
			
		||||
                REQUIRE(true);
 | 
			
		||||
                item.skip();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::repeated_uint32_u: {
 | 
			
		||||
                sum_of_u += item.get_uint32();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::required_Sub_submessage: {
 | 
			
		||||
                protozero::pbf_message<TestComplex::Sub> subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(sum_of_u == 66);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_message: all") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-all");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestComplex::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    int number_of_u = 0;
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case TestComplex::Test::required_fixed32_f: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::optional_int64_i: {
 | 
			
		||||
                REQUIRE(true);
 | 
			
		||||
                item.skip();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::optional_int64_j: {
 | 
			
		||||
                REQUIRE(item.get_int64() == 555555555LL);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::repeated_uint32_u: {
 | 
			
		||||
                item.skip();
 | 
			
		||||
                ++number_of_u;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::required_Sub_submessage: {
 | 
			
		||||
                protozero::pbf_message<TestComplex::Sub> subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            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);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case TestComplex::Test::optional_string_s: {
 | 
			
		||||
                REQUIRE(item.get_string() == "optionalstring");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(number_of_u == 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read complex data using pbf_message: skip everything") {
 | 
			
		||||
    const std::string buffer = load_data("complex/data-all");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_message<TestComplex::Test> item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case TestComplex::Test::required_fixed32_f:
 | 
			
		||||
            case TestComplex::Test::optional_int64_i:
 | 
			
		||||
            case TestComplex::Test::optional_int64_j:
 | 
			
		||||
            case TestComplex::Test::repeated_uint32_u:
 | 
			
		||||
            case TestComplex::Test::required_Sub_submessage:
 | 
			
		||||
            case TestComplex::Test::packed_sint32_d:
 | 
			
		||||
            case TestComplex::Test::optional_string_s:
 | 
			
		||||
                item.skip();
 | 
			
		||||
                break;
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_writer: minimal") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
    pw.add_fixed32(1, 12345678);
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_writer pws{submessage};
 | 
			
		||||
    pws.add_string(1, "foobar");
 | 
			
		||||
 | 
			
		||||
    pw.add_message(5, submessage);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case 1: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_writer: some") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw2{buffer};
 | 
			
		||||
    pw2.add_fixed32(1, 12345678);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_writer pw;
 | 
			
		||||
    using std::swap;
 | 
			
		||||
    swap(pw, pw2);
 | 
			
		||||
 | 
			
		||||
    REQUIRE(pw.valid());
 | 
			
		||||
    REQUIRE_FALSE(pw2.valid());
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_writer pws{submessage};
 | 
			
		||||
    pws.add_string(1, "foobar");
 | 
			
		||||
 | 
			
		||||
    pw.add_uint32(4, 22);
 | 
			
		||||
    pw.add_uint32(4, 44);
 | 
			
		||||
    pw.add_int64(2, -9876543);
 | 
			
		||||
    pw.add_message(5, submessage);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    uint32_t sum_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 4: {
 | 
			
		||||
                sum_of_u += item.get_uint32();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                const auto view = item.get_view();
 | 
			
		||||
                protozero::pbf_reader subitem{view};
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(std::string(subitem.get_view()) == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(sum_of_u == 66);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_writer: all") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
    pw.add_fixed32(1, 12345678);
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_writer pws{submessage};
 | 
			
		||||
    pws.add_string(1, "foobar");
 | 
			
		||||
    pw.add_message(5, submessage);
 | 
			
		||||
 | 
			
		||||
    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 int32_t d[] = { -17, 22 };
 | 
			
		||||
    pw.add_packed_sint32(7, std::begin(d), std::end(d));
 | 
			
		||||
 | 
			
		||||
    pw.add_int64(3, 555555555);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
                int32_t sum = 0;
 | 
			
		||||
                for (auto val : pi) {
 | 
			
		||||
                    sum += val;
 | 
			
		||||
                }
 | 
			
		||||
                REQUIRE(sum == 5);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 8: {
 | 
			
		||||
                REQUIRE(item.get_string() == "optionalstring");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(number_of_u == 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_builder: minimal") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Test> pw{buffer};
 | 
			
		||||
    pw.add_fixed32(TestComplex::Test::required_fixed32_f, 12345678);
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Sub> pws{submessage};
 | 
			
		||||
    pws.add_string(TestComplex::Sub::required_string_s, "foobar");
 | 
			
		||||
 | 
			
		||||
    pw.add_message(TestComplex::Test::required_Sub_submessage, submessage);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case 1: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 12345678L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_builder: some") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Test> pw2{buffer};
 | 
			
		||||
    pw2.add_fixed32(TestComplex::Test::required_fixed32_f, 12345678);
 | 
			
		||||
 | 
			
		||||
    std::string dummy_buffer;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Test> pw{dummy_buffer};
 | 
			
		||||
    using std::swap;
 | 
			
		||||
    swap(pw, pw2);
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Sub> pws{submessage};
 | 
			
		||||
    pws.add_string(TestComplex::Sub::required_string_s, "foobar");
 | 
			
		||||
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 22);
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 44);
 | 
			
		||||
    pw.add_int64(TestComplex::Test::optional_int64_i, -9876543);
 | 
			
		||||
    pw.add_message(TestComplex::Test::required_Sub_submessage, submessage);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    uint32_t sum_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 4: {
 | 
			
		||||
                sum_of_u += item.get_uint32();
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(sum_of_u == 66);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex data using pbf_builder: all") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Test> pw{buffer};
 | 
			
		||||
    pw.add_fixed32(TestComplex::Test::required_fixed32_f, 12345678);
 | 
			
		||||
 | 
			
		||||
    std::string submessage;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Sub> pws{submessage};
 | 
			
		||||
    pws.add_string(TestComplex::Sub::required_string_s, "foobar");
 | 
			
		||||
    pw.add_message(TestComplex::Test::required_Sub_submessage, submessage);
 | 
			
		||||
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 22);
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 44);
 | 
			
		||||
    pw.add_int64(TestComplex::Test::optional_int64_i, -9876543);
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 44);
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 66);
 | 
			
		||||
    pw.add_uint32(TestComplex::Test::repeated_uint32_u, 66);
 | 
			
		||||
 | 
			
		||||
    const int32_t 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);
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
                int32_t sum = 0;
 | 
			
		||||
                for (auto val : pi) {
 | 
			
		||||
                    sum += val;
 | 
			
		||||
                }
 | 
			
		||||
                REQUIRE(sum == 5);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 8: {
 | 
			
		||||
                REQUIRE(item.get_string() == "optionalstring");
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE(number_of_u == 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void check_message(const std::string& buffer) {
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    while (item.next()) {
 | 
			
		||||
        switch (item.tag()) {
 | 
			
		||||
            case 1: {
 | 
			
		||||
                REQUIRE(item.get_fixed32() == 42L);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case 5: {
 | 
			
		||||
                protozero::pbf_reader subitem = item.get_message();
 | 
			
		||||
                REQUIRE(subitem.next());
 | 
			
		||||
                REQUIRE(subitem.get_string() == "foobar");
 | 
			
		||||
                REQUIRE_FALSE(subitem.next());
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
                REQUIRE(false); // should not be here
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex with subwriter using pbf_writer") {
 | 
			
		||||
    std::string buffer_test;
 | 
			
		||||
    protozero::pbf_writer pbf_test{buffer_test};
 | 
			
		||||
    pbf_test.add_fixed32(1, 42L);
 | 
			
		||||
 | 
			
		||||
    SECTION("message in message") {
 | 
			
		||||
        protozero::pbf_writer pbf_submessage{pbf_test, 5};
 | 
			
		||||
        pbf_submessage.add_string(1, "foobar");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    check_message(buffer_test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write complex with subwriter using pbf_builder") {
 | 
			
		||||
    std::string buffer_test;
 | 
			
		||||
    protozero::pbf_builder<TestComplex::Test> pbf_test{buffer_test};
 | 
			
		||||
    pbf_test.add_fixed32(TestComplex::Test::required_fixed32_f, 42L);
 | 
			
		||||
 | 
			
		||||
    SECTION("message in message") {
 | 
			
		||||
        protozero::pbf_builder<TestComplex::Sub> pbf_submessage{pbf_test, TestComplex::Test::required_Sub_submessage};
 | 
			
		||||
        pbf_submessage.add_string(TestComplex::Sub::required_string_s, "foobar");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    check_message(buffer_test);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								third_party/protozero/test/t/complex/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								third_party/protozero/test/t/complex/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestComplex::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_f(12345678);
 | 
			
		||||
    TestComplex::Sub* submsg = msg.mutable_submessage();
 | 
			
		||||
    submsg->set_s("foobar");
 | 
			
		||||
 | 
			
		||||
    write_to_file(msg, "data-minimal.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.add_u(22);
 | 
			
		||||
    msg.add_u(44);
 | 
			
		||||
    msg.set_i(-9876543);
 | 
			
		||||
 | 
			
		||||
    write_to_file(msg, "data-some.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_s("optionalstring");
 | 
			
		||||
    msg.add_u(44);
 | 
			
		||||
    msg.add_u(66);
 | 
			
		||||
    msg.add_u(66);
 | 
			
		||||
    msg.add_d(-17);
 | 
			
		||||
    msg.add_d(22);
 | 
			
		||||
    msg.set_j(555555555);
 | 
			
		||||
 | 
			
		||||
    write_to_file(msg, "data-all.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								third_party/protozero/test/t/complex/testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								third_party/protozero/test/t/complex/testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestComplex;
 | 
			
		||||
 | 
			
		||||
message Sub {
 | 
			
		||||
    required string s = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
    required fixed32 f = 1;
 | 
			
		||||
    optional int64 i = 2;
 | 
			
		||||
    optional int64 j = 3;
 | 
			
		||||
    required Sub submessage = 5;
 | 
			
		||||
    optional string s = 8;
 | 
			
		||||
    repeated uint32 u = 4;
 | 
			
		||||
    repeated sint32 d = 7 [packed=true];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/double/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/double/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
	ラ」p=*ツタ
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/double/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/double/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
	<09>O<EFBFBD><4F>n<EFBFBD>@
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/double/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/double/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										11
									
								
								third_party/protozero/test/t/double/double_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								third_party/protozero/test/t/double/double_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestDouble;
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    required double x = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										73
									
								
								third_party/protozero/test/t/double/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								third_party/protozero/test/t/double/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,73 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read 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
 | 
			
		||||
    // is aligned before that, in at least one of these cases the double will
 | 
			
		||||
    // not be aligned properly. So we test that even in that case the double
 | 
			
		||||
    // will be extracted properly.
 | 
			
		||||
    for (std::string::size_type n = 0; n < 2; ++n) {
 | 
			
		||||
        std::string abuffer;
 | 
			
		||||
        abuffer.reserve(1000);
 | 
			
		||||
        abuffer.append(n, '\0');
 | 
			
		||||
 | 
			
		||||
        SECTION("zero") {
 | 
			
		||||
            abuffer.append(load_data("double/data-zero"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_double() == Approx(0.0));
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("positive") {
 | 
			
		||||
            abuffer.append(load_data("double/data-pos"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_double() == Approx(4.893));
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("negative") {
 | 
			
		||||
            abuffer.append(load_data("double/data-neg"));
 | 
			
		||||
            protozero::pbf_reader item{abuffer.data() + n, abuffer.size() - n};
 | 
			
		||||
 | 
			
		||||
            REQUIRE(item.next());
 | 
			
		||||
            REQUIRE(item.get_double() == Approx(-9232.33));
 | 
			
		||||
            REQUIRE_FALSE(item.next());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SECTION("end_of_buffer") {
 | 
			
		||||
            abuffer.append(load_data("double/data-neg"));
 | 
			
		||||
 | 
			
		||||
            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&);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write double field") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.add_double(1, 0.0);
 | 
			
		||||
        REQUIRE(buffer == load_data("double/data-zero"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        pw.add_double(1, 4.893);
 | 
			
		||||
        REQUIRE(buffer == load_data("double/data-pos"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        pw.add_double(1, -9232.33);
 | 
			
		||||
        REQUIRE(buffer == load_data("double/data-neg"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								third_party/protozero/test/t/double/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								third_party/protozero/test/t/double/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestDouble::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_x(0.0);
 | 
			
		||||
    write_to_file(msg, "data-zero.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_x(4.893);
 | 
			
		||||
    write_to_file(msg, "data-pos.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_x(-9232.33);
 | 
			
		||||
    write_to_file(msg, "data-neg.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								third_party/protozero/test/t/double/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								third_party/protozero/test/t/double/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#include "t/double/double_testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write double field and check with libprotobuf") {
 | 
			
		||||
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    TestDouble::Test msg;
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.add_double(1, 0.0);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.x() == Approx(0.0));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        pw.add_double(1, 4.893);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.x() == Approx(4.893));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        pw.add_double(1, -9232.33);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.x() == Approx(-9232.33));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/enum/data-black.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/enum/data-black.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								third_party/protozero/test/t/enum/data-blue.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/enum/data-blue.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/enum/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/enum/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<08><><EFBFBD><EFBFBD>
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/enum/data-min.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/enum/data-min.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<08><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/enum/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/enum/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<08><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
			
		||||
							
								
								
									
										25
									
								
								third_party/protozero/test/t/enum/enum_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								third_party/protozero/test/t/enum/enum_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestEnum;
 | 
			
		||||
 | 
			
		||||
enum Color {
 | 
			
		||||
    BLACK = 0;
 | 
			
		||||
    RED   = 1;
 | 
			
		||||
    GREEN = 2;
 | 
			
		||||
    BLUE  = 3;
 | 
			
		||||
    MAX   = 2147483646;
 | 
			
		||||
    NEG   = -1;
 | 
			
		||||
 | 
			
		||||
    // Older versions (before 2.6.0) of the google protobuf compiler have a
 | 
			
		||||
    // bug and don't allow the real minimum of -2147483648, so we are testing
 | 
			
		||||
    // with this.
 | 
			
		||||
    MIN   = -2147483647;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    required Color color = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										83
									
								
								third_party/protozero/test/t/enum/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								third_party/protozero/test/t/enum/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,83 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read enum field: zero") {
 | 
			
		||||
    const std::string buffer = load_data("enum/data-black");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_enum() == 0L);
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read enum field: positive") {
 | 
			
		||||
    const std::string buffer = load_data("enum/data-blue");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_enum() == 3L);
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read enum field: negative") {
 | 
			
		||||
    const std::string buffer = load_data("enum/data-neg");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_enum() == -1L);
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read enum field: max") {
 | 
			
		||||
    const std::string buffer = load_data("enum/data-max");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_enum() == std::numeric_limits<int32_t>::max());
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("read enum field: min") {
 | 
			
		||||
    const std::string buffer = load_data("enum/data-min");
 | 
			
		||||
 | 
			
		||||
    protozero::pbf_reader item{buffer};
 | 
			
		||||
 | 
			
		||||
    REQUIRE(item.next());
 | 
			
		||||
    REQUIRE(item.get_enum() == (std::numeric_limits<int32_t>::min() + 1));
 | 
			
		||||
    REQUIRE_FALSE(item.next());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write enum field") {
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.add_enum(1, 0L);
 | 
			
		||||
        REQUIRE(buffer == load_data("enum/data-black"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        pw.add_enum(1, 3L);
 | 
			
		||||
        REQUIRE(buffer == load_data("enum/data-blue"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        pw.add_enum(1, -1L);
 | 
			
		||||
        REQUIRE(buffer == load_data("enum/data-neg"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("max") {
 | 
			
		||||
        pw.add_enum(1, std::numeric_limits<int32_t>::max());
 | 
			
		||||
        REQUIRE(buffer == load_data("enum/data-max"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("min") {
 | 
			
		||||
        pw.add_enum(1, std::numeric_limits<int32_t>::min() + 1);
 | 
			
		||||
        REQUIRE(buffer == load_data("enum/data-min"));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								third_party/protozero/test/t/enum/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								third_party/protozero/test/t/enum/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestEnum::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_color(TestEnum::BLACK);
 | 
			
		||||
    write_to_file(msg, "data-black.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_color(TestEnum::BLUE);
 | 
			
		||||
    write_to_file(msg, "data-blue.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_color(TestEnum::NEG);
 | 
			
		||||
    write_to_file(msg, "data-neg.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_color(TestEnum::MAX);
 | 
			
		||||
    write_to_file(msg, "data-max.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_color(TestEnum::MIN);
 | 
			
		||||
    write_to_file(msg, "data-min.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										54
									
								
								third_party/protozero/test/t/enum/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								third_party/protozero/test/t/enum/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#include "t/enum/enum_testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write enum field and check with libprotobuf") {
 | 
			
		||||
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    TestEnum::Test msg;
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.add_enum(1, 0L);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.color() == TestEnum::Color::BLACK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("positive") {
 | 
			
		||||
        pw.add_enum(1, 3L);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.color() == TestEnum::Color::BLUE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("negative") {
 | 
			
		||||
        pw.add_enum(1, -1L);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.color() == TestEnum::Color::NEG);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("max") {
 | 
			
		||||
        pw.add_enum(1, std::numeric_limits<int32_t>::max() - 1);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.color() == TestEnum::Color::MAX);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("min") {
 | 
			
		||||
        pw.add_enum(1, std::numeric_limits<int32_t>::min() + 1);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.color() == TestEnum::Color::MIN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/fixed32/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/fixed32/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
<0A><><EFBFBD><EFBFBD>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-pos200.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-pos200.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed32/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										11
									
								
								third_party/protozero/test/t/fixed32/fixed32_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								third_party/protozero/test/t/fixed32/fixed32_testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestFixed32;
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    required fixed32 i = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								third_party/protozero/test/t/fixed32/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								third_party/protozero/test/t/fixed32/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#define PBF_TYPE fixed32
 | 
			
		||||
#define PBF_TYPE_IS_SIGNED 0
 | 
			
		||||
using cpp_type = uint32_t;
 | 
			
		||||
 | 
			
		||||
#include <scalar_access.hpp>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								third_party/protozero/test/t/fixed32/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								third_party/protozero/test/t/fixed32/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestFixed32::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_i(0);
 | 
			
		||||
    write_to_file(msg, "data-zero.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(1);
 | 
			
		||||
    write_to_file(msg, "data-pos.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(200);
 | 
			
		||||
    write_to_file(msg, "data-pos200.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(std::numeric_limits<uint32_t>::max());
 | 
			
		||||
    write_to_file(msg, "data-max.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								third_party/protozero/test/t/fixed32/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								third_party/protozero/test/t/fixed32/writer_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#include "t/fixed32/fixed32_testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
TEST_CASE("write fixed32 field and check with libprotobuf") {
 | 
			
		||||
 | 
			
		||||
    std::string buffer;
 | 
			
		||||
    protozero::pbf_writer pw{buffer};
 | 
			
		||||
 | 
			
		||||
    TestFixed32::Test msg;
 | 
			
		||||
 | 
			
		||||
    SECTION("zero") {
 | 
			
		||||
        pw.add_fixed32(1, 0);
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.i() == 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("max") {
 | 
			
		||||
        pw.add_fixed32(1, std::numeric_limits<uint32_t>::max());
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.i() == std::numeric_limits<uint32_t>::max());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SECTION("min") {
 | 
			
		||||
        pw.add_fixed32(1, std::numeric_limits<uint32_t>::min());
 | 
			
		||||
 | 
			
		||||
        msg.ParseFromString(buffer);
 | 
			
		||||
 | 
			
		||||
        REQUIRE(msg.i() == std::numeric_limits<uint32_t>::min());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/fixed64/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/fixed64/data-max.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
	<09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-pos.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-pos200.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-pos200.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								third_party/protozero/test/t/fixed64/data-zero.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										9
									
								
								third_party/protozero/test/t/fixed64/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								third_party/protozero/test/t/fixed64/reader_test_cases.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
 | 
			
		||||
#include <test.hpp>
 | 
			
		||||
 | 
			
		||||
#define PBF_TYPE fixed64
 | 
			
		||||
#define PBF_TYPE_IS_SIGNED 0
 | 
			
		||||
using cpp_type = uint64_t;
 | 
			
		||||
 | 
			
		||||
#include <scalar_access.hpp>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								third_party/protozero/test/t/fixed64/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								third_party/protozero/test/t/fixed64/testcase.cpp
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
 | 
			
		||||
#include <testcase.hpp>
 | 
			
		||||
#include "testcase.pb.h"
 | 
			
		||||
 | 
			
		||||
int main(int c, char *argv[]) {
 | 
			
		||||
    TestFixed64::Test msg;
 | 
			
		||||
 | 
			
		||||
    msg.set_i(0);
 | 
			
		||||
    write_to_file(msg, "data-zero.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(1);
 | 
			
		||||
    write_to_file(msg, "data-pos.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(200);
 | 
			
		||||
    write_to_file(msg, "data-pos200.pbf");
 | 
			
		||||
 | 
			
		||||
    msg.set_i(std::numeric_limits<uint64_t>::max());
 | 
			
		||||
    write_to_file(msg, "data-max.pbf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								third_party/protozero/test/t/fixed64/testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								third_party/protozero/test/t/fixed64/testcase.proto
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
 | 
			
		||||
option optimize_for = LITE_RUNTIME;
 | 
			
		||||
 | 
			
		||||
package TestFixed64;
 | 
			
		||||
 | 
			
		||||
message Test {
 | 
			
		||||
 | 
			
		||||
    required fixed64 i = 1;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								third_party/protozero/test/t/float/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								third_party/protozero/test/t/float/data-neg.pbf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
H瞽ソ
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue
	
	Block a user