blob: f41962acb4dcabd2861880ffcfcdb31d592c269e [file] [log] [blame]
Noah Richardsbbf7c862015-04-21 16:30:13 -07001/*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/bitbuffer.h"
12
13#include <limits>
14
15#include "webrtc/base/checks.h"
16
17namespace {
18
19// Returns the lowest (right-most) |bit_count| bits in |byte|.
20uint8 LowestBits(uint8 byte, size_t bit_count) {
21 DCHECK_LE(bit_count, 8u);
22 uint8 mask_shift = 8 - static_cast<uint8>(bit_count);
23 return byte & (0xFF >> mask_shift);
24}
25
26// Returns the highest (left-most) |bit_count| bits in |byte|, shifted to the
27// lowest bits (to the right).
28uint8 HighestBits(uint8 byte, size_t bit_count) {
29 DCHECK_LE(bit_count, 8u);
30 uint8 shift = 8 - static_cast<uint8>(bit_count);
31 uint8 mask = 0xFF << shift;
32 return (byte & mask) >> shift;
33}
34
35} // namespace
36
37namespace rtc {
38
39BitBuffer::BitBuffer(const uint8* bytes, size_t byte_count)
40 : bytes_(bytes), byte_count_(byte_count), byte_offset_(), bit_offset_() {
41 DCHECK(static_cast<uint64>(byte_count_) <=
42 std::numeric_limits<uint32>::max());
43}
44
45uint64 BitBuffer::RemainingBitCount() const {
46 return (static_cast<uint64>(byte_count_) - byte_offset_) * 8 - bit_offset_;
47}
48
49bool BitBuffer::ReadUInt8(uint8* val) {
50 uint32 bit_val;
51 if (!ReadBits(&bit_val, sizeof(uint8) * 8)) {
52 return false;
53 }
54 DCHECK(bit_val <= std::numeric_limits<uint8>::max());
55 *val = static_cast<uint8>(bit_val);
56 return true;
57}
58
59bool BitBuffer::ReadUInt16(uint16* val) {
60 uint32 bit_val;
61 if (!ReadBits(&bit_val, sizeof(uint16) * 8)) {
62 return false;
63 }
64 DCHECK(bit_val <= std::numeric_limits<uint16>::max());
65 *val = static_cast<uint16>(bit_val);
66 return true;
67}
68
69bool BitBuffer::ReadUInt32(uint32* val) {
70 return ReadBits(val, sizeof(uint32) * 8);
71}
72
73bool BitBuffer::PeekBits(uint32* val, size_t bit_count) {
74 if (!val || bit_count > RemainingBitCount() || bit_count > 32) {
75 return false;
76 }
77 const uint8* bytes = bytes_ + byte_offset_;
78 size_t remaining_bits_in_current_byte = 8 - bit_offset_;
79 uint32 bits = LowestBits(*bytes++, remaining_bits_in_current_byte);
80 // If we're reading fewer bits than what's left in the current byte, just
81 // return the portion of this byte that we need.
82 if (bit_count < remaining_bits_in_current_byte) {
83 *val = HighestBits(bits, bit_offset_ + bit_count);
84 return true;
85 }
86 // Otherwise, subtract what we've read from the bit count and read as many
87 // full bytes as we can into bits.
88 bit_count -= remaining_bits_in_current_byte;
89 while (bit_count >= 8) {
90 bits = (bits << 8) | *bytes++;
91 bit_count -= 8;
92 }
93 // Whatever we have left is smaller than a byte, so grab just the bits we need
94 // and shift them into the lowest bits.
95 if (bit_count > 0) {
96 bits <<= bit_count;
97 bits |= HighestBits(*bytes, bit_count);
98 }
99 *val = bits;
100 return true;
101}
102
103bool BitBuffer::ReadBits(uint32* val, size_t bit_count) {
104 return PeekBits(val, bit_count) && ConsumeBits(bit_count);
105}
106
107bool BitBuffer::ConsumeBytes(size_t byte_count) {
108 return ConsumeBits(byte_count * 8);
109}
110
111bool BitBuffer::ConsumeBits(size_t bit_count) {
112 if (bit_count > RemainingBitCount()) {
113 return false;
114 }
115
116 byte_offset_ += (bit_offset_ + bit_count) / 8;
117 bit_offset_ = (bit_offset_ + bit_count) % 8;
118 return true;
119}
120
121bool BitBuffer::ReadExponentialGolomb(uint32* val) {
122 if (!val) {
123 return false;
124 }
125 // Store off the current byte/bit offset, in case we want to restore them due
126 // to a failed parse.
127 size_t original_byte_offset = byte_offset_;
128 size_t original_bit_offset = bit_offset_;
129
130 // Count the number of leading 0 bits by peeking/consuming them one at a time.
131 size_t zero_bit_count = 0;
132 uint32 peeked_bit;
133 while (PeekBits(&peeked_bit, 1) && peeked_bit == 0) {
134 zero_bit_count++;
135 ConsumeBits(1);
136 }
137
138 // We should either be at the end of the stream, or the next bit should be 1.
139 DCHECK(!PeekBits(&peeked_bit, 1) || peeked_bit == 1);
140
141 // The bit count of the value is the number of zeros + 1. Make sure that many
142 // bits fits in a uint32 and that we have enough bits left for it, and then
143 // read the value.
144 size_t value_bit_count = zero_bit_count + 1;
145 if (value_bit_count > 32 || !ReadBits(val, value_bit_count)) {
146 byte_offset_ = original_byte_offset;
147 bit_offset_ = original_bit_offset;
148 return false;
149 }
150 *val -= 1;
151 return true;
152}
153
154} // namespace rtc