-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathFeiBitStreamer.h
131 lines (105 loc) · 3.09 KB
/
FeiBitStreamer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2019 by FEI Company
#ifndef FEIBITSTREAM_H
#define FEIBITSTREAM_H
#include <queue>
#include <iostream>
#include "stdint.h"
typedef uint8_t BitType;
typedef uint16_t MultiBitType;
typedef uint64_t BitStreamWordType;
const int BitStreamWordTypeNBits = 8 * sizeof(BitStreamWordType);
// NB: nWords not used, not checked anyware; responsibility of caller now.
class BitStreamer
{
public:
BitStreamer(BitStreamWordType* buffer) :
buffer(buffer), ptr(buffer), bitCounter(BitStreamWordTypeNBits)
{
curValue = *ptr;
}
// todo this can be optimized.
MultiBitType getBits(unsigned NBits)
{
MultiBitType r = curValue & ((1<<NBits)-1);
if (bitCounter <= NBits)
{
// take a new one.
curValue = *(++ptr);
auto xtraBitsToRead = NBits - bitCounter; //# Remaining bits.
r |= ((curValue & ((1<<xtraBitsToRead)-1)) << (bitCounter));
curValue >>= xtraBitsToRead;
bitCounter = BitStreamWordTypeNBits - xtraBitsToRead;
}
else
{
// just shift and done!
curValue >>= NBits;
bitCounter -= NBits;
}
return r;
}
void rewind(unsigned NBits)
{
//std::cout<<"REWIND "<<bitCounter<<", "<<curValue<<std::endl;
bitCounter += NBits;
if (bitCounter > BitStreamWordTypeNBits)
{
bitCounter -= BitStreamWordTypeNBits;
--ptr;
}
curValue = (*ptr) >> (BitStreamWordTypeNBits-bitCounter);
//std::cout<<"/REWINDED "<<bitCounter<<", "<<curValue<<std::endl;
}
uint64_t nWordsRead() const
{
return (ptr - buffer) + ((bitCounter == BitStreamWordTypeNBits)? 0 : 1);
}
BitStreamWordType* buffer;
private:
BitStreamWordType* ptr;
BitStreamWordType curValue;
size_t bitCounter;
};
class BitStreamWriter
{
public:
BitStreamWriter(BitStreamWordType* buf) :
ptr(buf), wordPos(0), counter(0)
{
*ptr = 0;
}
// todo this can be optimized.
void putBits(MultiBitType v, unsigned NBits)
{
v &= ((1 << NBits) - 1); // people are allowed to send words with more bits, for convenience.
if (wordPos + NBits < BitStreamWordTypeNBits)
{
// all fit in current word and 1 bit remains so no need to go to next word pos.
//put it there, and update word position and done.
(*ptr) |= (static_cast<BitStreamWordType>(v) << wordPos);
wordPos += NBits;
}
else
{
// wordPos+1 most sign.bits still fit in. put them in, update NBits, and go to next word position.
auto NBitsStillFit = BitStreamWordTypeNBits - wordPos;
(*ptr) |= static_cast<BitStreamWordType>((v & ((1<<NBitsStillFit)-1))) << wordPos;
v >>= NBitsStillFit;
// go to next pos;
++ptr; ++counter;
wordPos = NBits - NBitsStillFit;
*ptr = v;
}
}
size_t getWordSize()
{
size_t r = ((size_t)(counter));
if (wordPos > 0) r+=1;
return r;
}
private:
BitStreamWordType* ptr;
size_t counter;
BitStreamWordType wordPos;
};
#endif