1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buffer_source.h"
6*a03ca8b9SKrzysztof Kosiński
7*a03ca8b9SKrzysztof Kosiński #include <algorithm>
8*a03ca8b9SKrzysztof Kosiński
9*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/algorithm.h"
10*a03ca8b9SKrzysztof Kosiński
11*a03ca8b9SKrzysztof Kosiński namespace zucchini {
12*a03ca8b9SKrzysztof Kosiński
BufferSource(ConstBufferView buffer)13*a03ca8b9SKrzysztof Kosiński BufferSource::BufferSource(ConstBufferView buffer) : ConstBufferView(buffer) {}
14*a03ca8b9SKrzysztof Kosiński
Skip(size_type n)15*a03ca8b9SKrzysztof Kosiński BufferSource& BufferSource::Skip(size_type n) {
16*a03ca8b9SKrzysztof Kosiński remove_prefix(std::min(n, Remaining()));
17*a03ca8b9SKrzysztof Kosiński return *this;
18*a03ca8b9SKrzysztof Kosiński }
19*a03ca8b9SKrzysztof Kosiński
CheckNextBytes(std::initializer_list<uint8_t> bytes) const20*a03ca8b9SKrzysztof Kosiński bool BufferSource::CheckNextBytes(std::initializer_list<uint8_t> bytes) const {
21*a03ca8b9SKrzysztof Kosiński if (Remaining() < bytes.size())
22*a03ca8b9SKrzysztof Kosiński return false;
23*a03ca8b9SKrzysztof Kosiński return std::mismatch(bytes.begin(), bytes.end(), begin()).first ==
24*a03ca8b9SKrzysztof Kosiński bytes.end();
25*a03ca8b9SKrzysztof Kosiński }
26*a03ca8b9SKrzysztof Kosiński
ConsumeBytes(std::initializer_list<uint8_t> bytes)27*a03ca8b9SKrzysztof Kosiński bool BufferSource::ConsumeBytes(std::initializer_list<uint8_t> bytes) {
28*a03ca8b9SKrzysztof Kosiński if (!CheckNextBytes(bytes))
29*a03ca8b9SKrzysztof Kosiński return false;
30*a03ca8b9SKrzysztof Kosiński remove_prefix(bytes.size());
31*a03ca8b9SKrzysztof Kosiński return true;
32*a03ca8b9SKrzysztof Kosiński }
33*a03ca8b9SKrzysztof Kosiński
GetRegion(size_type count,ConstBufferView * buffer)34*a03ca8b9SKrzysztof Kosiński bool BufferSource::GetRegion(size_type count, ConstBufferView* buffer) {
35*a03ca8b9SKrzysztof Kosiński DCHECK_NE(begin(), nullptr);
36*a03ca8b9SKrzysztof Kosiński if (Remaining() < count)
37*a03ca8b9SKrzysztof Kosiński return false;
38*a03ca8b9SKrzysztof Kosiński *buffer = ConstBufferView(begin(), count);
39*a03ca8b9SKrzysztof Kosiński remove_prefix(count);
40*a03ca8b9SKrzysztof Kosiński return true;
41*a03ca8b9SKrzysztof Kosiński }
42*a03ca8b9SKrzysztof Kosiński
43*a03ca8b9SKrzysztof Kosiński // [0aaaaaaa] => 00000000'00000000'00000000'0aaaaaaa
44*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 0bbbbbbb] => 00000000'00000000'00bbbbbb'baaaaaaa
45*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 0ccccccc] => 00000000'000ccccc'ccbbbbbb'baaaaaaa
46*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 1ccccccc 0ddddddd] => 0000dddd'dddccccc'ccbbbbbb'baaaaaaa
47*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 1ccccccc 1ddddddd 0???eeee]
48*a03ca8b9SKrzysztof Kosiński // => eeeedddd'dddccccc'ccbbbbbb'baaaaaaa
49*a03ca8b9SKrzysztof Kosiński // Note that "???" is discarded. Meanwhile, 1???eeee is invalid.
GetUleb128(uint32_t * ret)50*a03ca8b9SKrzysztof Kosiński bool BufferSource::GetUleb128(uint32_t* ret) {
51*a03ca8b9SKrzysztof Kosiński int shift_lim =
52*a03ca8b9SKrzysztof Kosiński static_cast<int>(std::min<size_type>(kMaxLeb128Size, size())) * 7;
53*a03ca8b9SKrzysztof Kosiński const_iterator cur = cbegin();
54*a03ca8b9SKrzysztof Kosiński uint32_t value = 0U;
55*a03ca8b9SKrzysztof Kosiński for (int shift = 0; shift < shift_lim; shift += 7, ++cur) {
56*a03ca8b9SKrzysztof Kosiński uint32_t b = *cur;
57*a03ca8b9SKrzysztof Kosiński // When |shift == 28|, |(b & 0x7F) << shift| discards the "???" bits.
58*a03ca8b9SKrzysztof Kosiński value |= static_cast<uint32_t>(b & 0x7F) << shift;
59*a03ca8b9SKrzysztof Kosiński if (!(b & 0x80)) {
60*a03ca8b9SKrzysztof Kosiński *ret = value;
61*a03ca8b9SKrzysztof Kosiński seek(cur + 1);
62*a03ca8b9SKrzysztof Kosiński return true;
63*a03ca8b9SKrzysztof Kosiński }
64*a03ca8b9SKrzysztof Kosiński }
65*a03ca8b9SKrzysztof Kosiński return false;
66*a03ca8b9SKrzysztof Kosiński }
67*a03ca8b9SKrzysztof Kosiński
68*a03ca8b9SKrzysztof Kosiński // [0Saaaaaa] => SSSSSSSS'SSSSSSSS'SSSSSSSS'SSaaaaaa
69*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 0Sbbbbbb] => SSSSSSSS'SSSSSSSS'SSSbbbbb'baaaaaaa
70*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 0Scccccc] => SSSSSSSS'SSSScccc'ccbbbbbb'baaaaaaa
71*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 1ccccccc 0Sdddddd] => SSSSSddd'dddccccc'ccbbbbbb'baaaaaaa
72*a03ca8b9SKrzysztof Kosiński // [1aaaaaaa 1bbbbbbb 1ccccccc 1ddddddd 0???Seee]
73*a03ca8b9SKrzysztof Kosiński // => Seeedddd'dddccccc'ccbbbbbb'baaaaaaa
74*a03ca8b9SKrzysztof Kosiński // Note that "???" is discarded. Meanwhile, 1???eeee is invalid.
GetSleb128(int32_t * ret)75*a03ca8b9SKrzysztof Kosiński bool BufferSource::GetSleb128(int32_t* ret) {
76*a03ca8b9SKrzysztof Kosiński int shift_lim =
77*a03ca8b9SKrzysztof Kosiński static_cast<int>(std::min<size_type>(kMaxLeb128Size, size())) * 7;
78*a03ca8b9SKrzysztof Kosiński const_iterator cur = cbegin();
79*a03ca8b9SKrzysztof Kosiński int32_t value = 0;
80*a03ca8b9SKrzysztof Kosiński for (int shift = 0; shift < shift_lim; shift += 7, ++cur) {
81*a03ca8b9SKrzysztof Kosiński uint32_t b = *cur;
82*a03ca8b9SKrzysztof Kosiński // When |shift == 28|, |(b & 0x7F) << shift| discards the "???" bits.
83*a03ca8b9SKrzysztof Kosiński value |= static_cast<int32_t>(static_cast<uint32_t>(b & 0x7F) << shift);
84*a03ca8b9SKrzysztof Kosiński if (!(b & 0x80)) {
85*a03ca8b9SKrzysztof Kosiński *ret = (shift == 28) ? value : SignExtend(shift + 6, value);
86*a03ca8b9SKrzysztof Kosiński seek(cur + 1);
87*a03ca8b9SKrzysztof Kosiński return true;
88*a03ca8b9SKrzysztof Kosiński }
89*a03ca8b9SKrzysztof Kosiński }
90*a03ca8b9SKrzysztof Kosiński return false;
91*a03ca8b9SKrzysztof Kosiński }
92*a03ca8b9SKrzysztof Kosiński
SkipLeb128()93*a03ca8b9SKrzysztof Kosiński bool BufferSource::SkipLeb128() {
94*a03ca8b9SKrzysztof Kosiński int lim = static_cast<int>(std::min<size_type>(kMaxLeb128Size, size()));
95*a03ca8b9SKrzysztof Kosiński const_iterator cur = cbegin();
96*a03ca8b9SKrzysztof Kosiński for (int i = 0; i < lim; ++i, ++cur) {
97*a03ca8b9SKrzysztof Kosiński if (!(*cur & 0x80)) {
98*a03ca8b9SKrzysztof Kosiński seek(cur + 1);
99*a03ca8b9SKrzysztof Kosiński return true;
100*a03ca8b9SKrzysztof Kosiński }
101*a03ca8b9SKrzysztof Kosiński }
102*a03ca8b9SKrzysztof Kosiński return false;
103*a03ca8b9SKrzysztof Kosiński }
104*a03ca8b9SKrzysztof Kosiński
105*a03ca8b9SKrzysztof Kosiński } // namespace zucchini
106