text: // Copyright 2019 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef SQL_RECOVER_MODULE_INTEGERS_H_
  #define SQL_RECOVER_MODULE_INTEGERS_H_
  
  #include <cstdint>
  #include <limits>
  #include <utility>
  
  namespace sql
  {
  namespace recover
  {
  // Reads an unsigned 16-bit big-endian integer from the given buffer.
  //
  // |buffer| must point to at least two consecutive bytes of valid memory.
  //
  // The return type was chosen because it suits the callers best.
  inline int
  LoadBigEndianUint16(const uint8_t* buffer)
  {
      static_assert(std::numeric_limits<uint16_t>::max() <= std::numeric_limits<int>::max(),
                    "The value may overflow the return type");
      return (static_cast<int>(buffer[0]) << 8) | static_cast<int>(buffer[1]);
  }
  
  // Reads a signed 32-bit big-endian integer from the given buffer.
  //
  // |buffer| must point to at least four consecutive bytes of valid memory.
  inline int32_t
  LoadBigEndianInt32(const uint8_t* buffer)
  {
      // The code gets optimized to mov + bswap on x86_64, and to ldr + rev on ARM.
      return (static_cast<int32_t>(buffer[0]) << 24) | (static_cast<int32_t>(buffer[1]) << 16)
             | (static_cast<int32_t>(buffer[2]) << 8) | static_cast<int32_t>(buffer[3]);
  }
  
  // Reads a signed 64-bit big-endian integer from the given buffer.
  //
  // |buffer| must point to at least eight consecutive bytes of valid memory.
  inline int64_t
  LoadBigEndianInt64(const uint8_t* buffer)
  {
      // The code gets optimized to mov + bswap on x86_64, and to ldr + rev on ARM.
      return (static_cast<int64_t>(buffer[0]) << 56) | (static_cast<int64_t>(buffer[1]) << 48)
             | (static_cast<int64_t>(buffer[2]) << 40) | (static_cast<int64_t>(buffer[3]) << 32)
             | (static_cast<int64_t>(buffer[4]) << 24) | (static_cast<int64_t>(buffer[5]) << 16)
             | (static_cast<int64_t>(buffer[6]) << 8) | static_cast<int64_t>(buffer[7]);
  }
  
  // Reads a SQLite varint.
  //
  // SQLite varints decode to 64-bit integers, and take up at most 9 bytes.
  // If present, the 9th byte holds bits 56-63 of the integer. This deviates from
  // Google (protobuf, leveldb) varint encoding, where the last varint byte's top
  // bit is always 0.
  //
  // The implementation assumes that |buffer| and |buffer_end| point into the same
  // array of bytes, and that |buffer| < |buffer_end|. The implementation will
  // never compute a pointer value larger than |buffer_end|.
  //
  // Returns the parsed number and a pointer to the first byte past the number.
  // Per the rules above, the returned pointer is guaranteed to be between
  // |buffer| and |buffer_end|. The returned pointer is also guaranteed to be at
  // most |kMaxVarintSize| bytes past |buffer|.
  std::pair<int64_t, const uint8_t*>
  ParseVarint(const uint8_t* buffer, const uint8_t* buffer_end);
  
  // The maximum number of bytes used to store a SQLite varint.
  constexpr int kMaxVarintSize = 9;
  
  }  // namespace recover
  }  // namespace sql
  
  #endif  // SQL_RECOVER_MODULE_INTEGERS_H_
  