-
Notifications
You must be signed in to change notification settings - Fork 0
/
code.cpp
217 lines (181 loc) · 6.11 KB
/
code.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
* Autor: Jordan Jarolim (xjarol03)
* Datum: 16.2.2017
* Soubor: code.cpp
* Komentar: Soubor obsahuje hlavni fce coding a decoding ke kodovani a dekodovani vstupu + pomocne fce pro prevod mezi vector<bool> a char
*/
#include "code.hpp"
#include "ahed.hpp"
#include "tree.hpp"
#include <string>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <tuple>
#include <bitset>
using namespace std;
/**
* Handle coding process
* @param symbol to be encoded
* @param output stream
*/
void Code::coding(int64_t symbol, std::vector<int64_t> *output){
tuple<vector<int64_t>, Tree*> foundSymbol;
/* New symbol */
if (!(Tree::alreadySeen(symbol))){
foundSymbol = this->getCode(NYT);
output->insert(output->end(), get<0>(foundSymbol).begin(), get<0>(foundSymbol).end());
output->push_back(symbol);
Tree::_listOfUsedChars.push_back(symbol);
Tree::root->newSymbol(symbol);
}
/* Already seen */
else{
foundSymbol = this->getCode(symbol);
output->insert(output->end(), get<0>(foundSymbol).begin(), get<0>(foundSymbol).end());
if (get<1>(foundSymbol) != NULL)
get<1>(foundSymbol)->updateTree();
else{
cerr<<"Internal error\n";
exit (-1);
}
}
}
/**
* Find symbol and return its path + its node
* @param symbol to be found
* @return tuple<string, Tree*>
*/
tuple<vector<int64_t>, Tree*> Code::getCode(int64_t symbol){
vector<int64_t> pathPart;
Tree *found = Tree::root->findSymbol(symbol, Tree::root);
Tree *move = found;
/* Is that root? */
if (move != NULL){
while (move->parent != NULL){
if (move->parent->left == move)
pathPart.push_back(MOVE_LEFT);
else
pathPart.push_back(MOVE_RIGHT);
move = move->parent;
}
}
else if (Tree::root->left != NULL)
pathPart.push_back(1001);
reverse(pathPart.begin(), pathPart.end());
return make_tuple(pathPart,found);
}
/**
* Translate char to booles
* @param buffer Buffer of booleans
* @param symbol - symbol to be encoded
*/
void charToBool(vector<bool> *buffer, char symbol){
std::bitset<8> transformedChar(symbol);
for (size_t j = 0; j < transformedChar.size(); ++j) {
buffer->push_back(transformedChar[j]);
}
}
/**
* Read value from vector
* @param buffer - buffer of bools
* @param position - position of element
*/
bool popFront2(vector<bool> *buffer, int64_t *position){
return (*buffer)[*position];
}
/**
* Vector of bools to char
* @param buffer - buffer of bools
* @param position of first bool in symbol
* @param shift - length of symbol (bits)
*/
char boolToChar2(vector<bool> *buffer,int64_t *position, int shift){
int64_t symbol = 0;
int counter = 0;
for(int64_t i = (*position); i < (*position)+shift; i++){
symbol += ((*buffer)[i] << counter++);
}
return symbol;
}
/**
* Handle decoding process
* @param inputFile to decode
* @param outputFile file to be written
*/
void Code::decoding(tAHED *ahed, FILE *inputFile, FILE *outputFile){
tuple<vector<int64_t>, Tree*> foundSymbol;
int64_t symbol;
Tree* actualNode = Tree::root;
int64_t outputSize = 0, inputSize = 0;
/* actual position in vector fo bools */
int64_t vectorPostition = 0;
/* buffer of vector of bools */
vector<bool> buffer;
/* actual values - symbol on input or direction to be moved to */
bool actualBool;
int64_t actualSymbol;
/* Read file as booles */
while((symbol = fgetc(inputFile)) != EOF){
inputSize++;
charToBool(&buffer, symbol);
}
bool repeat = true;
while (repeat){
/* if is not leaf */
if (actualNode->left != NULL){
actualBool = popFront2(&buffer, &vectorPostition);
vectorPostition++;
/* move */
if (actualBool == 0)
actualNode = actualNode->left;
else if (actualBool == 1)
actualNode = actualNode->right;
}else{
/* read in the next 8/16-bit character */
if (actualNode->val == NYT || actualNode->val == ROOT){
/* Is this PEOF? */
actualSymbol = boolToChar2(&buffer, &vectorPostition, 16);
if ((unsigned short)actualSymbol != Tree::peof){
/* Read following symbol */
actualSymbol = boolToChar2(&buffer, &vectorPostition, 8);
vectorPostition += 8;
/* print it to the file */
if(outputFile)
fprintf(outputFile, "%c", (char)actualSymbol);
else
cout<<(char)actualSymbol;
outputSize++;
/* Update Tree */
if (!(Tree::alreadySeen(actualSymbol))){
Tree::_listOfUsedChars.push_back(actualSymbol);
Tree::root->newSymbol(actualSymbol);
}else{
foundSymbol = this->getCode(actualSymbol);
if (get<1>(foundSymbol) != NULL)
get<1>(foundSymbol)->updateTree();
else{
cerr<<"Internal error\n";
exit(-1);
}
}
actualNode = Tree::root;
}
else{
repeat = false;
}
/* Known symbol from Tree */
}else{
if(outputFile)
fprintf(outputFile, "%c", (char)actualNode->val);
else
cout<<(char)actualNode->val;
outputSize++;
actualNode->updateTree();
actualNode = Tree::root;
}
}
}
ahed->codedSize = inputSize;
ahed->uncodedSize = outputSize;
}