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(compression)
|
||||
add_subdirectory(database)
|
||||
add_subdirectory(network)
|
||||
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
|
||||
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)
|
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/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()
|
||||
|
||||
|
||||
|
|
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