Project
Loading...
Searching...
No Matches
BitstreamReader.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef BITSTREAMREADER_H
13#define BITSTREAMREADER_H
14
19
20#include <type_traits>
21#include <bitset>
22
23namespace o2
24{
25namespace algorithm
26{
27
48template <typename BufferType>
50{
51 public:
53 // for the moment we simply use pointers, but with some traits this can be extended to
54 // containers
55 using value_type = BufferType;
56 using iterator = const value_type*;
57 static constexpr size_t value_size = sizeof(value_type) * 8;
58 BitstreamReader() = delete;
60 : mStart(start), mEnd(end), mCurrent(mStart), mBitPosition(value_size)
61 {
62 }
63 ~BitstreamReader() = default;
64
67 bool good() const
68 {
69 return mBitPosition > 0;
70 }
71
74 bool eof() const
75 {
76 return mCurrent == mEnd && mBitPosition > 0;
77 }
78
80 void reset()
81 {
82 mCurrent = mStart;
83 mBitPosition = value_size;
84 }
85
93 template <typename T, size_t N = sizeof(T) * 8>
94 size_t peek(T& v)
95 {
96 static_assert(N <= sizeof(T) * 8);
97 return peek<T, false>(v, N);
98 }
99
105 template <typename T>
106 size_t peek(T& v, size_t bitlength)
107 {
108 return peek<T, true>(v, bitlength);
109 }
110
113 void seek(size_t bitlength)
114 {
115 while (good() && bitlength > 0 && mCurrent != mEnd) {
116 if (bitlength >= mBitPosition) {
117 bitlength -= mBitPosition;
118 mBitPosition = 0;
119 } else {
120 mBitPosition -= bitlength;
121 bitlength = 0;
122 }
123 if (mBitPosition == 0) {
124 mCurrent++;
125 mBitPosition = value_size;
126 }
127 }
128
129 if (bitlength > 0) {
130 mBitPosition = 0;
131 }
132 }
133
135 template <typename T, size_t N = sizeof(T) * 8>
136 T get()
137 {
138 T result;
139 peek<T, N>(result);
140 seek(N);
141 return result;
142 }
143
145 template <typename T>
146 T get(size_t bitlength = sizeof(T) * 8)
147 {
148 T result;
149 peek<T>(result, bitlength);
150 seek(bitlength);
151 return result;
152 }
153
160 template <typename FieldType, size_t N = sizeof(FieldType) * 8, typename ParentType = self_type>
161 class Bits
162 {
163 public:
164 using field_type = FieldType;
165 static_assert(N <= sizeof(FieldType) * 8);
167 : mParent(nullptr), mData(0), mLength(0)
168 {
169 }
170 Bits(ParentType* parent, FieldType&& data)
171 : mParent(parent), mData(std::move(data)), mLength(N)
172 {
173 }
175 : mParent(other.mParent), mData(std::move(other.mData)), mLength(other.mLength)
176 {
177 other.mParent = nullptr;
178 other.mLength = 0;
179 }
180
182 {
183 if (mParent) {
184 mParent->seek(mLength);
185 }
186 }
187
189 {
190 mParent = other.mParent;
191 mData = std::move(other.mData);
192 mLength = other.mLength;
193 other.mParent = nullptr;
194 other.mLength = 0;
195
196 return *this;
197 }
198
199 FieldType& operator*()
200 {
201 return mData;
202 }
203
204 void markUsed(size_t length)
205 {
206 mLength = length;
207 }
208
209 private:
210 ParentType* mParent;
211 FieldType mData;
212 size_t mLength;
213 };
214
216 template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
218 {
219 target = get<T>();
220 return *this;
221 }
222
224 template <size_t N>
225 self_type& operator>>(std::bitset<N>& target)
226 {
227 target = get<std::bitset<N>, N>();
228 return *this;
229 }
230
232 template <typename T>
234 {
235 T bitfield;
236 peek<T>(bitfield);
237 target = std::move(Bits<T>(this, std::move(bitfield)));
238 return *this;
239 }
240
241 private:
243 template <typename T, bool RuntimeCheck>
244 size_t peek(T& result, size_t bitlength)
245 {
246 if constexpr (RuntimeCheck) {
247 // the runtime check is disabled if bitlength is derived at compile time
248 if (bitlength > sizeof(T) * 8) {
249 throw std::length_error(std::string("requested bit length ") + std::to_string(bitlength) + " does not fit size of result data type " + std::to_string(sizeof(T) * 8));
250 }
251 }
252 result = 0;
253 size_t bitsToWrite = bitlength;
254 auto current = mCurrent;
255 auto bitsAvailable = mBitPosition;
256 while (bitsToWrite > 0 && current != mEnd) {
257 // extract available bits
258 value_type mask = ~value_type(0) >> (value_size - bitsAvailable);
259 if (bitsToWrite >= bitsAvailable) {
260 T value = (*current & mask) << (bitsToWrite - bitsAvailable);
261 result |= value;
262 bitsToWrite -= bitsAvailable;
263 bitsAvailable = 0;
264 } else {
265 value_type value = (*current & mask) >> (bitsAvailable - bitsToWrite);
266 result |= value;
267 bitsAvailable -= bitsToWrite;
268 bitsToWrite = 0;
269 }
270 if (bitsAvailable == 0) {
271 current++;
272 bitsAvailable = value_size;
273 }
274 }
275
276 return bitlength - bitsToWrite;
277 }
278
280 iterator mStart;
282 iterator mEnd;
284 iterator mCurrent;
286 size_t mBitPosition;
287};
288} // namespace algorithm
289} // namespace o2
290#endif
Helper class to get value of specified type which holds the number used bits.
auto & operator=(Bits< FieldType, N, ParentType > &&other)
Bits(ParentType *parent, FieldType &&data)
void seek(size_t bitlength)
size_t peek(T &v, size_t bitlength)
T get(size_t bitlength=sizeof(T) *8)
Get the next n and move the read position.
self_type & operator>>(T &target)
Read an integral value from the stream.
self_type & operator>>(Bits< T > &target)
Read a Bits object from the stream.
static constexpr size_t value_size
BitstreamReader(iterator start, iterator end)
void reset()
Reset the reader, start over at beginning.
T get()
Get the next n bits and move the read position.
self_type & operator>>(std::bitset< N > &target)
Read a bitstream value from the stream.
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum target
Definition glcorearb.h:1641
GLboolean * data
Definition glcorearb.h:298
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLuint start
Definition glcorearb.h:469
GLint GLuint mask
Definition glcorearb.h:291
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
VectorOfTObjectPtrs other