blob: f02d0c2846fddedbeadb773d392f9e2a44e96f15 [file] [log] [blame]
// 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_