1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "byte_input_stream.h"
18
19 #include "berberis/base/checks.h"
20
21 #include "leb128.h"
22
23 namespace nogrod {
24
ByteInputStream(const uint8_t * buffer,size_t size)25 ByteInputStream::ByteInputStream(const uint8_t* buffer, size_t size)
26 : buffer_(buffer), size_(size), offset_(0) {}
27
available() const28 bool ByteInputStream::available() const {
29 return offset_ < size_;
30 }
31
offset() const32 uint64_t ByteInputStream::offset() const {
33 return offset_;
34 }
35
ReadUint8()36 uint8_t ByteInputStream::ReadUint8() {
37 CHECK(offset_ < size_);
38 return buffer_[offset_++];
39 }
40
ReadUint16()41 uint16_t ByteInputStream::ReadUint16() {
42 uint16_t result;
43 CHECK(offset_ + sizeof(result) <= size_);
44 memcpy(&result, buffer_ + offset_, sizeof(result));
45 offset_ += sizeof(result);
46
47 return result;
48 }
49
ReadUint24()50 uint32_t ByteInputStream::ReadUint24() {
51 uint32_t result = 0;
52 CHECK_LE(offset_ + 3, size_);
53 memcpy(&result, buffer_ + offset_, 3);
54 offset_ += 3;
55
56 return result;
57 }
58
ReadUint32()59 uint32_t ByteInputStream::ReadUint32() {
60 uint32_t result;
61 CHECK(offset_ + sizeof(result) <= size_);
62 memcpy(&result, buffer_ + offset_, sizeof(result));
63 offset_ += sizeof(result);
64
65 return result;
66 }
67
ReadUint64()68 uint64_t ByteInputStream::ReadUint64() {
69 uint64_t result;
70 CHECK(offset_ + sizeof(result) <= size_);
71 memcpy(&result, buffer_ + offset_, sizeof(result));
72 offset_ += sizeof(result);
73
74 return result;
75 }
76
ReadLeb128()77 uint64_t ByteInputStream::ReadLeb128() {
78 uint64_t result;
79 size_t bytes = DecodeLeb128(buffer_ + offset_, size_ - offset_, &result);
80 offset_ += bytes;
81 return result;
82 }
83
ReadSleb128()84 int64_t ByteInputStream::ReadSleb128() {
85 int64_t result;
86 size_t bytes = DecodeSleb128(buffer_ + offset_, size_ - offset_, &result);
87 offset_ += bytes;
88 return result;
89 }
90
ReadBytes(uint64_t size)91 std::vector<uint8_t> ByteInputStream::ReadBytes(uint64_t size) {
92 CHECK_LE(offset_ + size, size_);
93 // WORKAROUND(http://b/227598583): libc++ on tm-dev branch crashes of you call std::vector c-tor
94 // with size = 0;
95 if (size == 0) return {};
96 // End of workaround
97 std::vector<uint8_t> result(size);
98 memcpy(result.data(), buffer_ + offset_, size);
99 offset_ += size;
100
101 return result;
102 }
103
ReadString()104 std::string ByteInputStream::ReadString() {
105 CHECK_LT(offset_, size_); // there should be a place for at least one 0
106
107 const char* candidate = reinterpret_cast<const char*>(buffer_ + offset_);
108 while (buffer_[offset_++] != 0) {
109 CHECK_LT(offset_, size_);
110 }
111
112 return std::string{candidate};
113 }
114
115 } // namespace nogrod
116