Added huffman encoding utility
This commit is contained in:
parent
705244786e
commit
707f577f31
@ -1050,6 +1050,16 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
ui->tableWidgetCalls->addAction(clearActionSep);
|
||||
ui->tableWidgetCalls->addAction(clearActionAll);
|
||||
|
||||
// TESTING :P
|
||||
qint64 a = QDateTime::currentSecsSinceEpoch();
|
||||
qDebug() << a << Varicode::pack64bits(a) << Varicode::unpack64bits(Varicode::pack64bits(a));
|
||||
qDebug() << a << Varicode::bitsToStr(Varicode::intToBits(a)) << Varicode::bitsToInt(Varicode::strToBits(Varicode::bitsToStr(Varicode::intToBits(a))));
|
||||
|
||||
auto input = "HELLO BRAVE NEW WORLD!";
|
||||
auto encoded = Varicode::huffEncode(input);
|
||||
auto decoded = Varicode::huffDecode(encoded);
|
||||
qDebug() << input << Varicode::bitsToStr(encoded) << decoded;
|
||||
|
||||
// this must be the last statement of constructor
|
||||
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
|
||||
}
|
||||
|
145
varicode.cpp
145
varicode.cpp
@ -1,6 +1,8 @@
|
||||
/**
|
||||
* (C) 2018 Jordan Sherer <kn4crd@gmail.com> - All Rights Reserved
|
||||
**/
|
||||
#include <QDebug>
|
||||
#include <QMap>
|
||||
|
||||
#include "varicode.h"
|
||||
|
||||
@ -10,6 +12,56 @@ QString grid_pattern = {R"((?<grid>[A-R]{2}[0-9]{2})+)"};
|
||||
QString callsign_pattern1 = {R"((?<callsign>[A-Z0-9/]{2,}))"};
|
||||
QString callsign_pattern2 = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){3,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"};
|
||||
|
||||
QMap<QChar, QString> huff = {
|
||||
// char code weight
|
||||
{' ' , "001" }, // 1300
|
||||
{'E' , "000" }, // 1270.2
|
||||
{'T' , "1100" }, // 905.6
|
||||
{'A' , "1010" }, // 816.7
|
||||
{'O' , "0111" }, // 750.7
|
||||
{'I' , "0101" }, // 696.6
|
||||
{'N' , "0100" }, // 674.9
|
||||
{'S' , "11111" }, // 632.7
|
||||
{'H' , "11110" }, // 609.4
|
||||
{'R' , "11101" }, // 598.7
|
||||
{'D' , "10111" }, // 425.3
|
||||
{'L' , "10110" }, // 402.5
|
||||
{'C' , "111001" }, // 278.2
|
||||
{'U' , "111000" }, // 275.8
|
||||
{'M' , "110111" }, // 240.6
|
||||
{'W' , "110110" }, // 236.0
|
||||
{'F' , "110100" }, // 222.8
|
||||
{'G' , "100111" }, // 201.5
|
||||
{'Q' , "100110" }, // 200
|
||||
{'Y' , "011010" }, // 197.4
|
||||
{'P' , "011001" }, // 192.9
|
||||
{'B' , "011000" }, // 149.2
|
||||
{'!' , "0110111" }, // 100
|
||||
{'.' , "1000000" }, // 100
|
||||
{'0' , "1000001" }, // 100
|
||||
{'1' , "1000010" }, // 100
|
||||
{'2' , "1000011" }, // 100
|
||||
{'3' , "1000100" }, // 100
|
||||
{'4' , "1000101" }, // 100
|
||||
{'5' , "1000110" }, // 100
|
||||
{'6' , "1000111" }, // 100
|
||||
{'7' , "1001000" }, // 100
|
||||
{'8' , "1001001" }, // 100
|
||||
{'9' , "1001010" }, // 100
|
||||
{'?' , "1001011" }, // 100
|
||||
{'^' , "1101010" }, // 100 <- shift
|
||||
{'V' , "0110110" }, // 97.8
|
||||
{'K' , "11010111" }, // 77.2
|
||||
{'J' , "1101011010" }, // 15.3
|
||||
{'X' , "1101011001" }, // 15.0
|
||||
{'Z' , "11010110110" }, // 7.4
|
||||
{':' , "11010110000" }, // 5
|
||||
{'+' , "110101100011" }, // 5
|
||||
{'-' , "110101101110" }, // 5
|
||||
{'/' , "110101101111" }, // 5
|
||||
{'\x04' , "110101100010" }, // 1 <- eot
|
||||
};
|
||||
|
||||
QStringList Varicode::parseCallsigns(QString const &input){
|
||||
QStringList callsigns;
|
||||
QRegularExpression re(callsign_pattern2);
|
||||
@ -47,11 +99,63 @@ QStringList Varicode::parseGrids(const QString &input){
|
||||
return grids;
|
||||
}
|
||||
|
||||
QVector<bool> Varicode::intToBits(qint64 value, int expected){
|
||||
QVector<bool> Varicode::huffEncode(QString const& text){
|
||||
QVector<bool> out;
|
||||
|
||||
foreach(auto ch, text){
|
||||
if(!huff.contains(ch)){
|
||||
continue;
|
||||
}
|
||||
out += strToBits(huff[ch]);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QString Varicode::huffDecode(QVector<bool> const& bitvec){
|
||||
QString out;
|
||||
|
||||
QString bits = bitsToStr(bitvec);
|
||||
|
||||
// TODO: jsherer - this is naive...
|
||||
while(bits.length() > 0){
|
||||
bool found = false;
|
||||
foreach(auto key, huff.keys()){
|
||||
if(bits.startsWith(huff[key])){
|
||||
out.append(key);
|
||||
bits = bits.mid(huff[key].length());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QVector<bool> Varicode::strToBits(QString const& bitvec){
|
||||
QVector<bool> bits;
|
||||
foreach(auto ch, bitvec){
|
||||
bits.append(ch == '1');
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
QString Varicode::bitsToStr(QVector<bool> const& bitvec){
|
||||
QString bits;
|
||||
foreach(auto bit, bitvec){
|
||||
bits.append(bit ? "1" : "0");
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
QVector<bool> Varicode::intToBits(quint64 value, int expected){
|
||||
QVector<bool> bits;
|
||||
|
||||
while(value){
|
||||
bits.prepend((bool) value & 1);
|
||||
bits.prepend((bool)(value & 1));
|
||||
value = value >> 1;
|
||||
}
|
||||
|
||||
@ -64,32 +168,33 @@ QVector<bool> Varicode::intToBits(qint64 value, int expected){
|
||||
return bits;
|
||||
}
|
||||
|
||||
qint64 Varicode::bitsToInt(QVector<bool> const value){
|
||||
qint64 v = 0;
|
||||
quint64 Varicode::bitsToInt(QVector<bool> const value){
|
||||
quint64 v = 0;
|
||||
foreach(bool bit, value){
|
||||
v = (v << 1) + (int)(bit);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
qint8 Varicode::unpack5bits(QString const& value){
|
||||
quint8 Varicode::unpack5bits(QString const& value){
|
||||
return alphabet.indexOf(value.at(0));
|
||||
}
|
||||
|
||||
QString Varicode::pack5bits(qint8 packed){
|
||||
QString Varicode::pack5bits(quint8 packed){
|
||||
return alphabet.at(packed % nalphabet);
|
||||
}
|
||||
|
||||
qint16 Varicode::unpack16bits(QString const& value){
|
||||
quint16 Varicode::unpack16bits(QString const& value){
|
||||
int a = alphabet.indexOf(value.at(0));
|
||||
int b = alphabet.indexOf(value.at(1));
|
||||
int c = alphabet.indexOf(value.at(2));
|
||||
return (nalphabet*nalphabet) * a + nalphabet*b + c;
|
||||
}
|
||||
|
||||
QString Varicode::pack16bits(qint16 packed){
|
||||
QString Varicode::pack16bits(quint16 packed){
|
||||
QString out;
|
||||
qint16 tmp = packed / (nalphabet*nalphabet);
|
||||
quint16 tmp = packed / (nalphabet*nalphabet);
|
||||
|
||||
out.append(alphabet.at(tmp));
|
||||
|
||||
tmp = (packed - (tmp * (nalphabet*nalphabet))) / nalphabet;
|
||||
@ -98,25 +203,27 @@ QString Varicode::pack16bits(qint16 packed){
|
||||
tmp = packed % nalphabet;
|
||||
out.append(alphabet.at(tmp));
|
||||
|
||||
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
qint32 Varicode::unpack32bits(QString const& value){
|
||||
return (qint32)unpack16bits(value.left(3)) << 16 | unpack16bits(value.right(3));
|
||||
quint32 Varicode::unpack32bits(QString const& value){
|
||||
return (quint32)(unpack16bits(value.left(3))) << 16 | unpack16bits(value.right(3));
|
||||
}
|
||||
|
||||
QString Varicode::pack32bits(qint32 packed){
|
||||
qint16 a = (packed & 0xFFFF0000) >> 16;
|
||||
qint16 b = packed & 0xFFFF;
|
||||
QString Varicode::pack32bits(quint32 packed){
|
||||
quint16 a = (packed & 0xFFFF0000) >> 16;
|
||||
quint16 b = packed & 0xFFFF;
|
||||
return pack16bits(a) + pack16bits(b);
|
||||
}
|
||||
|
||||
qint64 Varicode::unpack64bits(QString const& value){
|
||||
return (qint64)unpack16bits(value.left(6)) << 32 | unpack16bits(value.right(6));
|
||||
quint64 Varicode::unpack64bits(QString const& value){
|
||||
return (quint64)(unpack32bits(value.left(6))) << 32 | unpack32bits(value.right(6));
|
||||
}
|
||||
|
||||
QString Varicode::pack64bits(qint64 packed){
|
||||
qint32 a = (packed & 0xFFFFFFFF00000000) >> 32;
|
||||
qint32 b = packed & 0xFFFFFFFF;
|
||||
QString Varicode::pack64bits(quint64 packed){
|
||||
quint32 a = (packed & 0xFFFFFFFF00000000) >> 32;
|
||||
quint32 b = packed & 0xFFFFFFFF;
|
||||
return pack32bits(a) + pack32bits(b);
|
||||
}
|
||||
|
25
varicode.h
25
varicode.h
@ -20,21 +20,26 @@ public:
|
||||
static QStringList parseCallsigns(QString const &input);
|
||||
static QStringList parseGrids(QString const &input);
|
||||
|
||||
static QVector<bool> huffEncode(QString const& text);
|
||||
static QString huffDecode(QVector<bool> const& bitvec);
|
||||
|
||||
QVector<bool> intToBits(qint64 value, int expected=0);
|
||||
qint64 bitsToInt(QVector<bool> const value);
|
||||
static QVector<bool> strToBits(QString const& bitvec);
|
||||
static QString bitsToStr(QVector<bool> const& bitvec);
|
||||
|
||||
qint8 unpack5bits(QString const& value);
|
||||
QString pack5bits(qint8 packed);
|
||||
static QVector<bool> intToBits(quint64 value, int expected=0);
|
||||
static quint64 bitsToInt(QVector<bool> const value);
|
||||
|
||||
qint16 unpack16bits(QString const& value);
|
||||
QString pack16bits(qint16 packed);
|
||||
static quint8 unpack5bits(QString const& value);
|
||||
static QString pack5bits(quint8 packed);
|
||||
|
||||
qint32 unpack32bits(QString const& value);
|
||||
QString pack32bits(qint32 packed);
|
||||
static quint16 unpack16bits(QString const& value);
|
||||
static QString pack16bits(quint16 packed);
|
||||
|
||||
qint64 unpack64bits(QString const& value);
|
||||
QString pack64bits(qint64 packed);
|
||||
static quint32 unpack32bits(QString const& value);
|
||||
static QString pack32bits(quint32 packed);
|
||||
|
||||
static quint64 unpack64bits(QString const& value);
|
||||
static QString pack64bits(quint64 packed);
|
||||
};
|
||||
|
||||
#endif // VARICODE_H
|
||||
|
Loading…
Reference in New Issue
Block a user