summaryrefslogtreecommitdiff
path: root/chromium/sql/recover_module/integers.h
blob: f02d0c2846fddedbeadb773d392f9e2a44e96f15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 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_