-
Notifications
You must be signed in to change notification settings - Fork 0
/
CTrieDec.cpp
146 lines (127 loc) · 4.92 KB
/
CTrieDec.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
#include "CTrieDec.hpp"
//parameterloser Konstruktor; initialisiert Dictionary (mit ASCII-Alphabet)
CTrieDec::CTrieDec(){
for(int index=0; index<256; index++){
m_symbolTable[index].setSymbol(intToString(index));
m_symbolTable[index].setParent(-1);
//-2 wird standardmaeßig fuer alle Elemente gesetzt (siehe CKnot)
}
}
//Funktion zum Vergleichen der Werte mit einem Knoten
//koennte in Enc und Dec gemeinsam genutzt werden, um Duplication zu vermeiden
bool getHashValuesEqual(CKnot table[], int pos, int parent, const string& val){
return (table[pos].getParent()==parent && table[pos].getSymbol()==val);
}
//eigentliche Decodier-Funktion
string CTrieDec::decode(const vector<unsigned int>& encoded){
//wenn Eingabevektor leer, brich ab
if (encoded.empty()) {
return "";
}
string decoded = "";
//uA fuer Sonderfall (Eintrag noch nicht vollstaendig bekannt)
int lastHashValue = 0;
//Hashing-Singleton
CDoubleHashing& hasher = CDoubleHashing::getInstance();
//Versuchs-Zaehler fuer Rehashing
CForwardCounter attemptCounter;
//durch eingabevektor iterieren
for (unsigned int curIndex=0; curIndex<encoded.size(); curIndex++){
//aktuelles Zeichen decodieren
string curDecoded = m_symbolTable[encoded[curIndex]].getSymbol();
//wenn parent(s) vorhanden, diese zu curDecoded hinzufuegen (zsmbasteln)
if (m_symbolTable[encoded[curIndex]].getParent()!=-2) {
int index2 = m_symbolTable[encoded[curIndex]].getParent();
string parentstr="";
while (index2!=-1) {
//so lange, wie Parents vorhanden
//diese an den String anhaengen
parentstr+=m_symbolTable[index2].getSymbol();
index2=m_symbolTable[index2].getParent();
}
if (parentstr!="") {
//anschließend String invertieren und an curDecoded anhaengen
string tmpstr="";
for (int l=parentstr.length(); l>0; l--) {
tmpstr+=parentstr[l-1];
}
curDecoded=tmpstr+curDecoded;
}
}
//dieser string soll nur aus dem ersten Zeichen bestehen,...
string erstesZeichen = curDecoded;
//Sondefallbehandlung, wenn noetig
bool sonderfall = false;
if(m_symbolTable[encoded[curIndex]].getParent()==-2) {
sonderfall = true;
//erstes Zeichen des letzten Strings bekommen
int index=lastHashValue;
while (m_symbolTable[index].getParent()!=-1){
index=m_symbolTable[index].getParent();
}
erstesZeichen=m_symbolTable[index].getSymbol();
}
//... er wird hier gekuerzt
erstesZeichen = erstesZeichen.substr(0,1);
int position = encoded[curIndex];
//nur wenn erstes Zeichen schon verarbeitet
if (curIndex > 0) {
//Dictionary-Eintrag Anlegen
attemptCounter.setValue(0);
position = hasher.hash(lastHashValue, charToInt(erstesZeichen[0]), LZW_DICT_SIZE, 0);
//Rehashing
//wenn Position schon mit anderen Werten belegt (Kollision)
if (!getHashValuesEqual(m_symbolTable, position, lastHashValue, erstesZeichen)){
//Wird auch ausgefuehrt, wenn unbelegt (parent=-2)
//dann wird aber nicht die Schleife durchlaufen
//neue Variable fuer Hashwert -> warum? Steht in der Aufgabenstellung
//(Gegen Endlossschleife), aber es werden doch nur I und J sowie der Zaehler benutzt
int newPosition = position;
//neu hashen, bis leeres Feld oder der Wert gefunden wurde
while ((m_symbolTable[newPosition].getParent()!=-2) || (getHashValuesEqual(m_symbolTable, newPosition, lastHashValue, erstesZeichen))) {
//todo: Remove hacky shit, negating above produces endless loop
if (getHashValuesEqual(m_symbolTable, newPosition, lastHashValue, intToString(encoded[curIndex]))) break;
//Versuchszaehler inkrementieren
attemptCounter.count();
//neu hashen (veraenderter Zaehlerstand)
newPosition = hasher.hash(lastHashValue, charToInt(erstesZeichen[0]), LZW_DICT_SIZE, attemptCounter.getValue());
}
//Wenn leeres Feld oder das Feld mit dem Wert gefunden wurde,
//neue Position uebernehmen
position=newPosition;
}
//Eintrag anlegen
m_symbolTable[position].setSymbol(erstesZeichen);
m_symbolTable[position].setParent(lastHashValue);
lastHashValue=encoded[curIndex];
} else {
lastHashValue=encoded[curIndex];
}
//Sonderfallbehandlung
if (sonderfall) {
curDecoded = m_symbolTable[encoded[curIndex]].getSymbol();
//wenn parent(s) vorhanden, diese zu curDecoded hinzufuegen (zsmbasteln)
if (m_symbolTable[encoded[curIndex]].getParent()!=-2) {
int index2 = m_symbolTable[encoded[curIndex]].getParent();
string parentstr="";
while (index2!=-1) {
//so lange, wie Parents vorhanden
//diese an den String anhaengen
parentstr+=m_symbolTable[index2].getSymbol();
index2=m_symbolTable[index2].getParent();
}
if (parentstr!="") {
//anschließend String invertieren und an curDecoded anhaengen
string tmpstr="";
for (int l=parentstr.length(); l>0; l--) {
tmpstr+=parentstr[l-1];
}
curDecoded=tmpstr+curDecoded;
}
}
}
//String an den decodierten Ausgabestring anhaengen
decoded += curDecoded;
}
return decoded;
}