This repository has been archived by the owner on Jan 26, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbinary.cc
147 lines (126 loc) · 5.24 KB
/
binary.cc
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2015-2018 RWTH Aachen University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "binary.hh"
#include <stdexcept>
using namespace std;
//adds the bits to the end of the bits set
void Binary::push_back(uint64_t bits, uint8_t numberOfBits) {
//numberOfBits must be smaller than the max number of bits in the return type
assert(numberOfBits <= 64 && numberOfBits > 0);
//add the bits to the end
uint32_t oldBitOffset = bitOffset;
bitOffset = nextFreeBit;
if(mem == NULL) { //init the memory, if needed
uint8_t neededBytes = ceil(numberOfBits / 8.); //space in bytes that we need
uint16_t allocate = initMallocSize; //initMallocSize can be used to preserve space in advance (min. reallocs)
if(neededBytes > initMallocSize) //ensure that we get enough space to avoid reallocs
allocate = neededBytes;
mem = (uint8_t *) malloc(allocate);
if(mem != NULL) {
allocatedBytes = allocate;
}
else
throw "Malloc failed!";
}
else {
uint16_t neededBytes = ceil((bitOffset + numberOfBits) / 8.);
if(neededBytes > allocatedBytes) { //just reserve new space if needed
//double the allocated memory in this case to reduce the number of needed reallocs
uint32_t newAllocatedBytes = allocatedBytes * 2;
uint8_t *new_mem = (uint8_t *) realloc(mem, newAllocatedBytes);
if(new_mem != NULL) {
mem = new_mem;
allocatedBytes = newAllocatedBytes;
}
else
throw "Reallocation failed!";
}
}
//add the bits to the binary memory
//MSB of value should be the MSB of the value in the binary
for(int16_t position = numberOfBits - 1; position >= 0; position--, bitOffset++) {
//get the bit value of position in the first bit
uint8_t bit = (bits & (((uint64_t) 1) << position)) >> position;
uint8_t mask = 1 << (7 - bitOffset % 8);
if(bit == 1) //set bit
mem[bitOffset / 8] |= mask; //add the bit to the next free position in the binary
else //clear bit
mem[bitOffset / 8] &= ~mask; //add the bit to the next free position in the binary
}
nextFreeBit = bitOffset; //store the position of the next free bit in the bit set
bitOffset = oldBitOffset; //restore to the old position in the bit set
}
uint64_t Binary::next(uint8_t numberOfBits) {
//numberOfBits must be smaller than the max number of bits in the return type
assert(numberOfBits <= 64 && numberOfBits > 0);
assert(mem != NULL);
uint64_t value = 0;
for(int8_t valuePos = numberOfBits - 1; valuePos >= 0; valuePos--, bitOffset++) { //mem is always from MSB to LSB
//get the next bit from the memory
uint64_t bit = (mem[bitOffset / 8] >> (7 - (bitOffset % 8))) & 1; //next mem bit at LSB
bit <<= valuePos; //shift the bit from the memory to the right position
value |= bit; //set the bit inside the value
}
return value;
}
uint64_t Binary::at(uint64_t offset, uint8_t numberOfBits) {
//numberOfBits must be smaller than the max number of bits in the return type
assert(numberOfBits <= 64 && numberOfBits > 0);
assert(mem != NULL);
uint64_t value = 0;
for(int8_t valuePos = numberOfBits - 1; valuePos >= 0; valuePos--, offset++) { //mem is always from MSB to LSB
//get the next bit from the memory
uint64_t bit = (mem[offset / 8] >> (7 - (offset % 8))) & 1; //next mem bit at LSB
bit <<= valuePos; //shift the bit from the memory to the right position
value |= bit; //set the bit inside the value
}
return value;
}
uint64_t Binary::getPosition() {
return bitOffset;
}
void Binary::setPosition(uint64_t newPosition) {
bitOffset = newPosition;
}
void Binary::print() {
for(uint32_t position = 0; position < nextFreeBit; position++)
cout << at(position, 1);
cout << endl;
}
void Binary::write(string filename) {
ofstream file(filename);
if(!file.is_open())
throw runtime_error("Can't open file "+ filename);
// write output to filename
for(uint32_t position = 0; position < nextFreeBit; position += 8)
file << (uint8_t)( at(position, 8) >> (sizeof(uint64_t) - 8) );
file.close();
}
void Binary::read_from_file(string filename) {
ifstream file(filename, ios::binary);
if(!file.is_open())
throw runtime_error("Can't open file "+ filename);
//read the file into string
uint8_t value;
while(file.read((char *)(&value), sizeof(value))) {
push_back(value, sizeof(value)*8);
}
file.close();
}
uint32_t Binary::size() {
return nextFreeBit;
}
uint8_t *Binary::getPointer() {
return mem;
}