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