Mercurial > dedupe
changeset 20:754e12c927b3
Class for decoding binary datarepresentations, eg. Huffman trees.
| author | Tom Fredrik Blenning Klaussen <bfg@blenning.no> |
|---|---|
| date | Wed, 05 Sep 2012 21:54:18 +0200 |
| parents | 1ad6fa6dc039 |
| children | 3bcdb8bb6914 |
| files | BitDecoder.hpp TestBitDecoder.cpp |
| diffstat | 2 files changed, 139 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BitDecoder.hpp Wed Sep 05 21:54:18 2012 +0200 @@ -0,0 +1,101 @@ +#ifndef BITDECODER_HPP +#define BITDECODER_HPP + +#include <QtCore/QPair> +#include <QtCore/QDebug> +#include <QtCore/QBitArray> + +class BitDecoder { + BitDecoder* low; + BitDecoder* high; + QString _data; + +private: + BitDecoder(BitDecoder* low_in, BitDecoder* high_in) : low(low_in), high(high_in) + { + } + + +public: + BitDecoder(const QString& d) : low(0), high(0), _data(d) + { + } + + ~BitDecoder() + { + delete low; + delete high; + } + + const QString& data() const + { + return _data; + } + + QPair<QString, uint> decode(const QBitArray& bits, uint offset) + { + if (_data.isNull()) { + QPair<QString, uint> retVal = (bits[offset]?high:low)->decode(bits, offset + 1); + ++retVal.second; + return retVal; + } + else { + return QPair<QString, uint>(_data, 1); + } + } + + QString decode(const QBitArray& bits) + { + QPair<QString, uint> d; + QString combined; + uint n = bits.size(); + for (uint decodedBits = 0; decodedBits < n; decodedBits += d.second - 1) { + d = decode(bits, decodedBits); + combined.append(d.first); + } + return combined; + } + + static BitDecoder* merge(BitDecoder* low, BitDecoder* high) + { + return new BitDecoder(low, high); + } + + static QBitArray unite(const QBitArray& first, const QBitArray& second) + { + QBitArray result(first.size() + second.size()); + int n = first.size(); + for (int i = 0; i < n; ++i) { + result[i] = first[i]; + } + for (int i = 0; i < second.size(); ++i) { + result[n + i] = second[i]; + } + return result; + } + + QMap<QString, QBitArray> createEncoder() const + { + QMap<QString, QBitArray> retVal; + if (!_data.isNull()) { + retVal.insert(_data, QBitArray()); + } + if (low) { + QMap<QString, QBitArray> vals = low->createEncoder(); + for(QMap<QString, QBitArray>::const_iterator it = vals.begin(); + it != vals.end(); ++it) { + retVal.insert(it.key(), unite(QBitArray(1, false), it.value())); + } + } + if (high) { + QMap<QString, QBitArray> vals = high->createEncoder(); + for(QMap<QString, QBitArray>::const_iterator it = vals.begin(); + it != vals.end(); ++it) { + retVal.insert(it.key(), unite(QBitArray(1, true), it.value())); + } + } + return retVal; + } +}; + +#endif //BITDECODER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestBitDecoder.cpp Wed Sep 05 21:54:18 2012 +0200 @@ -0,0 +1,38 @@ +#include "BitDecoder.hpp" +#include "TestFramework.hpp" + +#include "InvalidDataException.hpp" +#include <QtCore/QDebug> + +QBitArray bitsFromString(const QString& str) +{ + QBitArray bits(str.size()); + for (int i = 0; i < str.size(); ++i) { + if (str[i] == '1') + bits[i] = true; + else if (str[i] == '0') + bits[i] = false; + else + throw InvalidDataException(); + } + return bits; +} + +BOOST_AUTO_TEST_CASE( TestSimple ) +{ + BitDecoder* up = new BitDecoder("a"); + BitDecoder* down = new BitDecoder("b"); + + BitDecoder* full = BitDecoder::merge(down, up); + + BOOST_REQUIRE(full->data().isNull()); + BOOST_REQUIRE_EQUAL(up->data(), "a"); + BOOST_REQUIRE_EQUAL(down->data(), "b"); + + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("1")), "a"); + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("0")), "b"); + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("1111")), "aaaa"); + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("0000")), "bbbb"); + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("1101")), "aaba"); + BOOST_REQUIRE_EQUAL(full->decode(bitsFromString("1111")), "aaaa"); +}
