zigzag.h 895 B

123456789101112131415161718192021
  1. #pragma once
  2. #include <util/generic/typetraits.h>
  3. #include <limits.h>
  4. //! Convert signed values to unsigned. Convenient for further varint encoding.
  5. //! See https://developers.google.com/protocol-buffers/docs/encoding#types for details.
  6. template <typename TSignedInt>
  7. inline auto ZigZagEncode(TSignedInt n) -> std::make_unsigned_t<TSignedInt> {
  8. static_assert(std::is_signed<TSignedInt>::value && std::is_integral<TSignedInt>::value, "Expected signed integral type.");
  9. auto un = static_cast<std::make_unsigned_t<TSignedInt>>(n);
  10. return (un << 1) ^ (n >> (CHAR_BIT * sizeof(TSignedInt) - 1));
  11. }
  12. template <typename TUnsignedInt>
  13. inline auto ZigZagDecode(TUnsignedInt n) -> std::make_signed_t<TUnsignedInt> {
  14. static_assert(std::is_unsigned<TUnsignedInt>::value, "Expected unsigned integral type.");
  15. return (n >> 1) ^ -static_cast<std::make_signed_t<TUnsignedInt>>(n & 1);
  16. }