Initial compresison.

This commit is contained in:
jmsgrogan 2022-08-01 16:14:14 +01:00
parent 4fce4fc614
commit 1ee31596fb
11 changed files with 195 additions and 1 deletions

View file

@ -1,4 +1,5 @@
add_subdirectory(core)
add_subdirectory(compression)
add_subdirectory(database)
add_subdirectory(network)
add_subdirectory(geometry)

View file

@ -0,0 +1,15 @@
list(APPEND compression_LIB_INCLUDES
StreamCompressor.cpp
HuffmanEncoder.cpp
)
add_library(compression SHARED ${compression_LIB_INCLUDES})
target_include_directories(compression PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
)
target_link_libraries(compression PUBLIC core)
set_property(TARGET compression PROPERTY FOLDER src)
set_target_properties( compression PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )

View file

@ -0,0 +1,77 @@
#include "HuffmanEncoder.h"
#include "Tree.h"
#include <unordered_map>
#include <queue>
#include <tuple>
#include <iostream>
void HuffmanEncoder::encode(const HuffmanEncoder::DataStream& stream)
{
std::unordered_map<unsigned char, unsigned> counts;
for (auto c : stream)
{
counts[c]++;
}
using CountPair = std::pair<unsigned char, unsigned>;
auto cmp = [](CountPair left, CountPair right)
{
return left.second > right.second;
};
std::priority_queue<CountPair, std::vector<CountPair>, decltype(cmp)> q(cmp);
for (const auto& entry : counts)
{
q.push({entry.first, entry.second});
}
NodePtr<CountPair> lastNode;
while(!q.empty())
{
const auto charData = q.top();
auto characterNode = std::make_unique<Node<CountPair> >(charData);
q.pop();
if (!lastNode)
{
const auto rightCharData = q.top();
auto rightCharacterNode = std::make_unique<Node<CountPair> >(rightCharData);
q.pop();
const auto sum = charData.second + rightCharData.second;
CountPair data{0, sum};
auto midNode = std::make_unique<Node<CountPair> >(data);
midNode->addChild(std::move(characterNode));
midNode->addChild(std::move(rightCharacterNode));
lastNode = std::move(midNode);
}
else
{
const auto sum = lastNode->getData().second;
CountPair data{0, sum};
auto midNode = std::make_unique<Node<CountPair> >(data);
if (charData.second < lastNode->getData().second)
{
midNode->addChild(std::move(lastNode));
midNode->addChild(std::move(characterNode));
}
else
{
midNode->addChild(std::move(characterNode));
midNode->addChild(std::move(lastNode));
}
lastNode = std::move(midNode);
}
}
Tree<CountPair> tree;
tree.addRootNode(std::move(lastNode));
//using TableEntry = std::tuple<>
std::cout << "********" << std::endl;
}

View file

@ -0,0 +1,11 @@
#pragma once
#include <vector>
class HuffmanEncoder
{
using DataStream = std::vector<unsigned char>;
public:
void encode(const DataStream& stream);
};

View file

View file

@ -0,0 +1,6 @@
#pragma once
class StreamCompressor
{
};

View file

@ -15,6 +15,7 @@ list(APPEND core_LIB_INCLUDES
Dictionary.cpp
Color.cpp
CommandLineArgs.cpp
data_structures/Tree.cpp
loggers/FileLogger.cpp
file_utilities/File.cpp
file_utilities/FileFormats.cpp
@ -35,6 +36,7 @@ target_include_directories(core PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
"${CMAKE_CURRENT_SOURCE_DIR}/streams"
"${CMAKE_CURRENT_SOURCE_DIR}/data_structures"
)
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
set_property(TARGET core PROPERTY FOLDER src)

View file

View file

@ -0,0 +1,66 @@
#pragma once
#include <memory>
template<typename T>
class Node
{
public:
Node(T data)
: mData(data)
{}
void addChild(std::unique_ptr<Node> child)
{
if(!mLeftChild)
{
mLeftChild = std::move(child);
}
else
{
mRightChild = std::move(child);
}
}
bool isLeaf() const
{
return !mLeftChild && !mRightChild;
}
T getData() const
{
return mData;
}
private:
T mData;
unsigned char mTag{0};
std::unique_ptr<Node> mLeftChild;
std::unique_ptr<Node> mRightChild;
};
template<typename T>
using NodePtr = std::unique_ptr<Node<T> >;
template<typename T>
class Tree
{
public:
Tree()
{
}
void addRootNode(NodePtr<T> root)
{
mRootNode = std::move(root);
}
Node<T>* getRootNode() const
{
return mRootNode.get();
}
private:
NodePtr<T> mRootNode;
};

View file

@ -11,6 +11,7 @@ list(APPEND TestFiles
audio/TestAudioWriter.cpp
audio/TestMidiReader.cpp
core/TestBinaryStream.cpp
compression/TestStreamCompressor.cpp
database/TestDatabase.cpp
fonts/TestFontReader.cpp
graphics/TestOpenGlRendering.cpp
@ -30,6 +31,7 @@ list(APPEND TestNames
TestAudioWriter
TestMidiReader
TestBinaryStream
TestStreamCompressor
TestDatabase
TestFontReader
TestOpenGlRendering
@ -52,7 +54,7 @@ link_directories(${DBUS_LIBRARY_DIRS})
foreach(TestFile TestName IN ZIP_LISTS TestFiles TestNames)
add_executable(${TestName} ${TestFile})
target_link_libraries(${TestName} PUBLIC core fonts network image publishing video database geometry audio graphics web client test_utils ${DBUS_LIBRARIES})
target_link_libraries(${TestName} PUBLIC core compression fonts network image publishing video database geometry audio graphics web client test_utils ${DBUS_LIBRARIES})
endforeach()

View file

@ -0,0 +1,14 @@
#include <iostream>
#include "HuffmanEncoder.h"
int main()
{
std::string testData = "BCAADDDCCACACAC";
std::vector<unsigned char> stream(testData.begin(), testData.end());
HuffmanEncoder encoder;
encoder.encode(stream);
return 0;
}