RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
ByteStream.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2017 Axel Waggershauser
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#pragma once
23
24#include "rawspeedconfig.h"
25#include "adt/Casts.h"
26#include "adt/Invariant.h"
27#include "io/Buffer.h"
28#include "io/IOException.h"
29#include <algorithm>
30#include <array>
31#include <cassert>
32#include <cstdint>
33#include <iterator>
34#include <limits>
35#include <string_view>
36
37#ifndef NDEBUG
38#include "AddressSanitizer.h"
39#endif
40
41namespace rawspeed {
42
43class ByteStream final : public DataBuffer {
45 0; // position of stream in bytes (this is next byte to deliver)
46
47public:
48 ByteStream() = default;
49
50 explicit ByteStream(DataBuffer buffer) : DataBuffer(buffer) {}
51
52 // return ByteStream that starts at given offset
53 // i.e. this->data + offset == getSubStream(offset).data
54 [[nodiscard]] ByteStream getSubStream(size_type offset,
55 size_type size_) const {
56 return ByteStream(DataBuffer(getSubView(offset, size_), getByteOrder()));
57 }
58
59 [[nodiscard]] ByteStream getSubStream(size_type offset) const {
60 return ByteStream(DataBuffer(getSubView(offset), getByteOrder()));
61 }
62
63 [[nodiscard]] size_type check(size_type bytes) const {
64 if (!isValid(pos, bytes))
65 ThrowIOE("Out of bounds access in ByteStream");
66 [[maybe_unused]] Buffer tmp = getSubView(pos, bytes);
67 assert(tmp.getSize() == bytes);
69 return bytes;
70 }
71
72 [[nodiscard]] size_type check(size_type nmemb, size_type size_) const {
73 if (size_ && nmemb > std::numeric_limits<size_type>::max() / size_)
74 ThrowIOE("Integer overflow when calculating stream length");
75 return check(nmemb * size_);
76 }
77
78 [[nodiscard]] size_type getPosition() const {
79 invariant(getSize() >= pos);
80 (void)check(0);
81 return pos;
82 }
83 void setPosition(size_type newPos) {
84 pos = newPos;
85 (void)check(0);
86 }
87 [[nodiscard]] size_type RAWSPEED_READONLY getRemainSize() const {
88 invariant(getSize() >= pos);
89 (void)check(0);
90 return getSize() - pos;
91 }
92 [[nodiscard]] const uint8_t* peekData(size_type count) const {
93 return Buffer::getSubView(pos, count).begin();
94 }
95 const uint8_t* getData(size_type count) {
96 const uint8_t* ret = peekData(count);
97 pos += count;
98 return ret;
99 }
100 [[nodiscard]] Buffer peekBuffer(size_type size_) const {
101 return getSubView(pos, size_);
102 }
104 Buffer ret = peekBuffer(size_);
105 pos += size_;
106 return ret;
107 }
108 [[nodiscard]] Buffer peekRemainingBuffer() const {
109 return getSubView(pos, getRemainSize());
110 }
111 [[nodiscard]] ByteStream peekStream(size_type size_) const {
112 return getSubStream(pos, size_);
113 }
114 [[nodiscard]] ByteStream peekStream(size_type nmemb, size_type size_) const {
115 if (size_ && nmemb > std::numeric_limits<size_type>::max() / size_)
116 ThrowIOE("Integer overflow when calculating stream length");
117 return peekStream(nmemb * size_);
118 }
120 ByteStream ret = peekStream(size_);
121 pos += size_;
122 return ret;
123 }
125 if (size_ && nmemb > std::numeric_limits<size_type>::max() / size_)
126 ThrowIOE("Integer overflow when calculating stream length");
127 return getStream(nmemb * size_);
128 }
129
130 void skipBytes(size_type nbytes) { pos += check(nbytes); }
131 void skipBytes(size_type nmemb, size_type size_) {
132 pos += check(nmemb, size_);
133 }
134
135 [[nodiscard]] bool hasPatternAt(std::string_view pattern,
136 size_type relPos) const {
137 if (!isValid(pos + relPos, implicit_cast<size_type>(pattern.size())))
138 return false;
139 auto tmp =
140 getSubView(pos + relPos, implicit_cast<size_type>(pattern.size()));
141 assert(tmp.getSize() == pattern.size());
142 return std::equal(tmp.begin(), tmp.end(), pattern.begin());
143 }
144
145 [[nodiscard]] bool hasPrefix(std::string_view prefix) const {
146 return hasPatternAt(prefix, /*relPos=*/0);
147 }
148
149 bool skipPrefix(std::string_view prefix) {
150 bool has_prefix = hasPrefix(prefix);
151 if (has_prefix)
152 pos += prefix.size();
153 return has_prefix;
154 }
155
156 template <typename T> [[nodiscard]] T peek(size_type i = 0) const {
157 return DataBuffer::get<T>(pos, i);
158 }
159 template <typename T> T get() {
160 auto ret = peek<T>();
161 pos += sizeof(T);
162 return ret;
163 }
164
165 template <typename T, int N> std::array<T, N> getArray() {
166 std::array<T, N> out;
167 auto bs = getStream(N, sizeof(T));
168 std::generate(out.begin(), out.end(), [&bs]() { return bs.get<T>(); });
169 invariant(bs.getRemainSize() == 0);
170 return out;
171 }
172
173 template <typename T> std::vector<T> getVector(int nElt) {
174 std::vector<T> out;
175 auto bs = getStream(nElt, sizeof(T));
176 out.reserve(nElt);
177 std::generate_n(std::back_inserter(out), nElt,
178 [&bs]() { return bs.get<T>(); });
179 invariant(bs.getRemainSize() == 0);
180 return out;
181 }
182
183 [[nodiscard]] uint8_t peekByte(size_type i = 0) const {
184 return peek<uint8_t>(i);
185 }
186 uint8_t getByte() { return get<uint8_t>(); }
187
188 [[nodiscard]] uint16_t peekU16() const { return peek<uint16_t>(); }
189
190 [[nodiscard]] uint32_t peekU32(size_type i = 0) const {
191 return peek<uint32_t>(i);
192 }
193
197 float getFloat() { return get<float>(); }
198
199 [[nodiscard]] std::string_view peekString() const {
201 const auto* termIter = std::find(tmp.begin(), tmp.end(), '\0');
202 if (termIter == tmp.end())
203 ThrowIOE("String is not null-terminated");
204 std::string_view::size_type strlen = std::distance(tmp.begin(), termIter);
205 return {reinterpret_cast<const char*>(tmp.begin()), strlen};
206 }
207
208 // Increments the stream to after the next zero byte and returns the bytes in
209 // between (not a copy). If the first byte is zero, stream is incremented one.
210 [[nodiscard]] std::string_view getString() {
211 std::string_view str = peekString();
213 return str;
214 }
215};
216
217} // namespace rawspeed
#define ThrowIOE(...)
Definition IOException.h:37
#define invariant(expr)
Definition Invariant.h:27
assert(dim.area() >=area)
ByteStream()=default
Buffer getSubView(size_type offset, size_type size_) const
Definition Buffer.h:78
bool isValid(size_type offset, size_type count=1) const
Definition Buffer.h:117
const uint8_t * begin() const
Definition Buffer.h:99
const uint8_t * end() const
Definition Buffer.h:102
size_type RAWSPEED_READONLY getSize() const
Definition Buffer.h:115
uint32_t size_type
Definition Buffer.h:49
void skipBytes(size_type nmemb, size_type size_)
Definition ByteStream.h:131
ByteStream getStream(size_type nmemb, size_type size_)
Definition ByteStream.h:124
uint16_t peekU16() const
Definition ByteStream.h:188
ByteStream getSubStream(size_type offset) const
Definition ByteStream.h:59
std::string_view peekString() const
Definition ByteStream.h:199
size_type check(size_type bytes) const
Definition ByteStream.h:63
size_type RAWSPEED_READONLY getRemainSize() const
Definition ByteStream.h:87
std::array< T, N > getArray()
Definition ByteStream.h:165
void setPosition(size_type newPos)
Definition ByteStream.h:83
Buffer getBuffer(size_type size_)
Definition ByteStream.h:103
const uint8_t * getData(size_type count)
Definition ByteStream.h:95
ByteStream getSubStream(size_type offset, size_type size_) const
Definition ByteStream.h:54
bool hasPrefix(std::string_view prefix) const
Definition ByteStream.h:145
uint32_t peekU32(size_type i=0) const
Definition ByteStream.h:190
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
std::string_view getString()
Definition ByteStream.h:210
ByteStream(DataBuffer buffer)
Definition ByteStream.h:50
ByteStream peekStream(size_type size_) const
Definition ByteStream.h:111
ByteStream peekStream(size_type nmemb, size_type size_) const
Definition ByteStream.h:114
uint8_t peekByte(size_type i=0) const
Definition ByteStream.h:183
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
size_type check(size_type nmemb, size_type size_) const
Definition ByteStream.h:72
const uint8_t * peekData(size_type count) const
Definition ByteStream.h:92
T peek(size_type i=0) const
Definition ByteStream.h:156
bool skipPrefix(std::string_view prefix)
Definition ByteStream.h:149
Buffer peekBuffer(size_type size_) const
Definition ByteStream.h:100
std::vector< T > getVector(int nElt)
Definition ByteStream.h:173
size_type getPosition() const
Definition ByteStream.h:78
bool hasPatternAt(std::string_view pattern, size_type relPos) const
Definition ByteStream.h:135
Buffer peekRemainingBuffer() const
Definition ByteStream.h:108
Endianness getByteOrder() const
Definition Buffer.h:154
T get(size_type offset, size_type index=0) const
Definition Buffer.h:147
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
throw T(buf.data())
static bool RegionIsPoisoned(const volatile void *addr, size_t size)