Initial compresison.
This commit is contained in:
parent
4fce4fc614
commit
1ee31596fb
11 changed files with 195 additions and 1 deletions
|
@ -1,4 +1,5 @@
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
|
add_subdirectory(compression)
|
||||||
add_subdirectory(database)
|
add_subdirectory(database)
|
||||||
add_subdirectory(network)
|
add_subdirectory(network)
|
||||||
add_subdirectory(geometry)
|
add_subdirectory(geometry)
|
||||||
|
|
15
src/compression/CMakeLists.txt
Normal file
15
src/compression/CMakeLists.txt
Normal 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 )
|
77
src/compression/HuffmanEncoder.cpp
Normal file
77
src/compression/HuffmanEncoder.cpp
Normal 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;
|
||||||
|
}
|
11
src/compression/HuffmanEncoder.h
Normal file
11
src/compression/HuffmanEncoder.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class HuffmanEncoder
|
||||||
|
{
|
||||||
|
using DataStream = std::vector<unsigned char>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void encode(const DataStream& stream);
|
||||||
|
};
|
0
src/compression/StreamCompressor.cpp
Normal file
0
src/compression/StreamCompressor.cpp
Normal file
6
src/compression/StreamCompressor.h
Normal file
6
src/compression/StreamCompressor.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class StreamCompressor
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
|
@ -15,6 +15,7 @@ list(APPEND core_LIB_INCLUDES
|
||||||
Dictionary.cpp
|
Dictionary.cpp
|
||||||
Color.cpp
|
Color.cpp
|
||||||
CommandLineArgs.cpp
|
CommandLineArgs.cpp
|
||||||
|
data_structures/Tree.cpp
|
||||||
loggers/FileLogger.cpp
|
loggers/FileLogger.cpp
|
||||||
file_utilities/File.cpp
|
file_utilities/File.cpp
|
||||||
file_utilities/FileFormats.cpp
|
file_utilities/FileFormats.cpp
|
||||||
|
@ -35,6 +36,7 @@ target_include_directories(core PUBLIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
|
"${CMAKE_CURRENT_SOURCE_DIR}/loggers"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
|
"${CMAKE_CURRENT_SOURCE_DIR}/memory"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/streams"
|
"${CMAKE_CURRENT_SOURCE_DIR}/streams"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/data_structures"
|
||||||
)
|
)
|
||||||
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||||
set_property(TARGET core PROPERTY FOLDER src)
|
set_property(TARGET core PROPERTY FOLDER src)
|
0
src/core/data_structures/Tree.cpp
Normal file
0
src/core/data_structures/Tree.cpp
Normal file
66
src/core/data_structures/Tree.h
Normal file
66
src/core/data_structures/Tree.h
Normal 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;
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ list(APPEND TestFiles
|
||||||
audio/TestAudioWriter.cpp
|
audio/TestAudioWriter.cpp
|
||||||
audio/TestMidiReader.cpp
|
audio/TestMidiReader.cpp
|
||||||
core/TestBinaryStream.cpp
|
core/TestBinaryStream.cpp
|
||||||
|
compression/TestStreamCompressor.cpp
|
||||||
database/TestDatabase.cpp
|
database/TestDatabase.cpp
|
||||||
fonts/TestFontReader.cpp
|
fonts/TestFontReader.cpp
|
||||||
graphics/TestOpenGlRendering.cpp
|
graphics/TestOpenGlRendering.cpp
|
||||||
|
@ -30,6 +31,7 @@ list(APPEND TestNames
|
||||||
TestAudioWriter
|
TestAudioWriter
|
||||||
TestMidiReader
|
TestMidiReader
|
||||||
TestBinaryStream
|
TestBinaryStream
|
||||||
|
TestStreamCompressor
|
||||||
TestDatabase
|
TestDatabase
|
||||||
TestFontReader
|
TestFontReader
|
||||||
TestOpenGlRendering
|
TestOpenGlRendering
|
||||||
|
@ -52,7 +54,7 @@ link_directories(${DBUS_LIBRARY_DIRS})
|
||||||
|
|
||||||
foreach(TestFile TestName IN ZIP_LISTS TestFiles TestNames)
|
foreach(TestFile TestName IN ZIP_LISTS TestFiles TestNames)
|
||||||
add_executable(${TestName} ${TestFile})
|
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()
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
|
14
test/compression/TestStreamCompressor.cpp
Normal file
14
test/compression/TestStreamCompressor.cpp
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue