summaryrefslogtreecommitdiffstats
path: root/Tools/MCADefrag
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Tools/MCADefrag/CMakeLists.txt8
-rw-r--r--Tools/MCADefrag/Globals.cpp10
-rw-r--r--Tools/MCADefrag/Globals.h174
-rw-r--r--Tools/MCADefrag/MCADefrag.cpp84
-rw-r--r--Tools/MCADefrag/MCADefrag.h17
5 files changed, 68 insertions, 225 deletions
diff --git a/Tools/MCADefrag/CMakeLists.txt b/Tools/MCADefrag/CMakeLists.txt
index 6ad894390..86a16b98a 100644
--- a/Tools/MCADefrag/CMakeLists.txt
+++ b/Tools/MCADefrag/CMakeLists.txt
@@ -17,10 +17,6 @@ function(flatten_files arg1)
endfunction()
-# Include the libraries:
-
-add_subdirectory(../../lib/zlib ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/lib/zlib)
-
# Include the shared files:
set(SHARED_SRC
../../src/StringCompression.cpp
@@ -66,11 +62,9 @@ source_group("Shared\\OSSupport" FILES ${SHARED_OSS_SRC} ${SHARED_OSS_HDR})
# Include the main source files:
set(SOURCES
MCADefrag.cpp
- Globals.cpp
)
set(HEADERS
MCADefrag.h
- Globals.h
)
source_group("" FILES ${SOURCES} ${HEADERS})
@@ -84,7 +78,7 @@ add_executable(MCADefrag
${SHARED_OSS_HDR}
)
-target_link_libraries(MCADefrag zlib fmt::fmt Threads::Threads)
+target_link_libraries(MCADefrag fmt::fmt libdeflate Threads::Threads)
include(../../SetFlags.cmake)
set_exe_flags(MCADefrag)
diff --git a/Tools/MCADefrag/Globals.cpp b/Tools/MCADefrag/Globals.cpp
deleted file mode 100644
index 13c6ae709..000000000
--- a/Tools/MCADefrag/Globals.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-
-// Globals.cpp
-
-// This file is used for precompiled header generation in MSVC environments
-
-#include "Globals.h"
-
-
-
-
diff --git a/Tools/MCADefrag/Globals.h b/Tools/MCADefrag/Globals.h
deleted file mode 100644
index def1fbdb9..000000000
--- a/Tools/MCADefrag/Globals.h
+++ /dev/null
@@ -1,174 +0,0 @@
-
-// Globals.h
-
-// This file gets included from every module in the project, so that global symbols may be introduced easily
-// Also used for precompiled header generation in MSVC environments
-
-
-
-
-
-// Compiler-dependent stuff:
-#if defined(_MSC_VER)
- // MSVC produces warning C4481 on the override keyword usage, so disable the warning altogether
- #pragma warning(disable:4481)
-
- // Disable some warnings that we don't care about:
- #pragma warning(disable:4100)
-
-#elif defined(__GNUC__)
-
- // TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
- #define abstract
-
-#else
-
- #error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
-
-#endif
-
-
-
-
-
-// Integral types with predefined sizes:
-typedef long long Int64;
-typedef int Int32;
-typedef short Int16;
-
-typedef unsigned long long UInt64;
-typedef unsigned int UInt32;
-typedef unsigned short UInt16;
-
-typedef unsigned char Byte;
-
-
-
-
-
-// A macro to disallow the copy constructor and operator= functions
-// This should be used in the private: declarations for any class that shouldn't allow copying itself
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName &); \
- void operator=(const TypeName &)
-
-// A macro that is used to mark unused function parameters, to avoid pedantic warnings in gcc
-#define UNUSED(X) (void)(X)
-
-
-
-
-// OS-dependent stuff:
-#ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <Windows.h>
- #include <winsock2.h>
- #include <ws2tcpip.h>
-
- // Windows SDK defines min and max macros, messing up with our std::min and std::max usage
- #undef min
- #undef max
-
- // Windows SDK defines GetFreeSpace as a constant, probably a Win16 API remnant
- #ifdef GetFreeSpace
- #undef GetFreeSpace
- #endif // GetFreeSpace
-
- #define SocketError WSAGetLastError()
-#else
- #include <sys/types.h>
- #include <sys/stat.h> // for mkdir
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <dirent.h>
- #include <iostream>
- #include <unistd.h>
-
- #include <cstring>
- #include <pthread.h>
- #include <semaphore.h>
- #include <cerrno>
- #include <fcntl.h>
-
- typedef int SOCKET;
- enum
- {
- INVALID_SOCKET = -1,
- };
- #define closesocket close
- #define SocketError errno
-#endif
-
-
-
-
-
-// CRT stuff:
-#include <cassert>
-#include <cstdio>
-#include <cmath>
-#include <cstdarg>
-#include <ctime>
-
-
-
-
-
-// STL stuff:
-#include <vector>
-#include <list>
-#include <deque>
-#include <string>
-#include <map>
-#include <algorithm>
-#include <memory>
-#include <atomic>
-#include <mutex>
-#include <thread>
-#include <condition_variable>
-
-
-
-
-// Common headers (without macros):
-#include "fmt.h"
-#include "LoggerSimple.h"
-#include "StringUtils.h"
-#include "OSSupport/CriticalSection.h"
-#include "OSSupport/Event.h"
-#include "OSSupport/IsThread.h"
-#include "OSSupport/File.h"
-
-
-
-
-
-// Common definitions:
-
-/** Evaluates to the number of elements in an array (compile-time!) */
-#define ARRAYCOUNT(X) (sizeof(X) / sizeof(*(X)))
-
-/** Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it, "(32 KiB)") */
-#define KiB * 1024
-#define MiB * 1024 * 1024
-
-/** Faster than (int)floorf((float)x / (float)div) */
-#define FAST_FLOOR_DIV(x, div) ((x) < 0 ? (((int)x / div) - 1) : ((int)x / div))
-
-// Own version of assert() that writes failed assertions to the log for review
-#ifdef NDEBUG
- #define ASSERT(x) ((void)0)
-#else
- #define ASSERT assert
-#endif
-
-// Pretty much the same as ASSERT() but stays in Release builds
-#define VERIFY(x) (!!(x) || (LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__), exit(1), 0))
-
-
-
-
-
diff --git a/Tools/MCADefrag/MCADefrag.cpp b/Tools/MCADefrag/MCADefrag.cpp
index c7886da35..d11505d45 100644
--- a/Tools/MCADefrag/MCADefrag.cpp
+++ b/Tools/MCADefrag/MCADefrag.cpp
@@ -8,7 +8,6 @@
#include "Logger.h"
#include "LoggerSimple.h"
#include "LoggerListeners.h"
-#include "zlib/zlib.h"
@@ -129,7 +128,8 @@ AString cMCADefrag::GetNextFileName(void)
cMCADefrag::cThread::cThread(cMCADefrag & a_Parent) :
super("MCADefrag thread"),
m_Parent(a_Parent),
- m_IsChunkUncompressed(false)
+ m_IsChunkUncompressed(false),
+ m_Compressor(12) // Set the highest compression factor
{
}
@@ -384,27 +384,33 @@ bool cMCADefrag::cThread::UncompressChunkGzip(void)
bool cMCADefrag::cThread::UncompressChunkZlib(void)
{
- // Uncompress the data:
- z_stream strm;
- strm.zalloc = nullptr;
- strm.zfree = nullptr;
- strm.opaque = nullptr;
- inflateInit(&strm);
- strm.next_out = m_RawChunkData;
- strm.avail_out = sizeof(m_RawChunkData);
- strm.next_in = m_CompressedChunkData + 1; // The first byte is the compression method, skip it
- strm.avail_in = static_cast<uInt>(m_CompressedChunkDataSize);
- int res = inflate(&strm, Z_FINISH);
- inflateEnd(&strm);
- if (res != Z_STREAM_END)
+ try
{
- LOGWARNING("Failed to uncompress chunk data: %s", strm.msg);
+ // Uncompress the data
+
+ const auto ExtractedData = m_Extractor.ExtractZLib(
+ {
+ reinterpret_cast<const std::byte *>(m_CompressedChunkData + 1), // The first byte is the compression method, skip it
+ static_cast<size_t>(m_CompressedChunkDataSize - 1)
+ });
+ const auto Extracted = ExtractedData.GetView();
+
+ if (Extracted.size() > MAX_RAW_CHUNK_DATA_SIZE)
+ {
+ LOGINFO("Too much data for the internal decompression buffer!");
+ return false;
+ }
+
+ std::copy(Extracted.begin(), Extracted.end(), reinterpret_cast<std::byte *>(m_RawChunkData));
+ m_RawChunkDataSize = static_cast<int>(Extracted.size());
+
+ return true;
+ }
+ catch (const std::exception & Oops)
+ {
+ LOGWARNING("Failed to uncompress chunk data. %s", Oops.what());
return false;
}
- ASSERT(strm.total_out < static_cast<uLong>(std::numeric_limits<int>::max()));
- m_RawChunkDataSize = static_cast<int>(strm.total_out);
-
- return true;
}
@@ -413,23 +419,33 @@ bool cMCADefrag::cThread::UncompressChunkZlib(void)
bool cMCADefrag::cThread::CompressChunk(void)
{
- // Check that the compressed data can fit:
- uLongf CompressedSize = compressBound(static_cast<uLong>(m_RawChunkDataSize));
- if (CompressedSize > sizeof(m_CompressedChunkData))
+ try
{
- LOGINFO("Too much data for the internal compression buffer!");
- return false;
- }
+ // Compress the data (using the highest compression factor, as set in the constructor)
+
+ const auto CompressedData = m_Compressor.CompressZLib(
+ {
+ reinterpret_cast<const std::byte *>(m_RawChunkData),
+ static_cast<size_t>(m_RawChunkDataSize)
+ });
+ const auto Compressed = CompressedData.GetView();
+
+ // Check that the compressed data can fit:
+ if (Compressed.size() > MAX_COMPRESSED_CHUNK_DATA_SIZE)
+ {
+ LOGINFO("Too much data for the internal compression buffer!");
+ return false;
+ }
+
+ m_CompressedChunkData[0] = COMPRESSION_ZLIB;
+ std::copy(Compressed.begin(), Compressed.end(), reinterpret_cast<std::byte *>(m_CompressedChunkData + 1));
+ m_CompressedChunkDataSize = static_cast<int>(Compressed.size()) + 1;
- // Compress the data using the highest compression factor:
- int errorcode = compress2(m_CompressedChunkData + 1, &CompressedSize, m_RawChunkData, static_cast<uLong>(m_RawChunkDataSize), Z_BEST_COMPRESSION);
- if (errorcode != Z_OK)
+ return true;
+ }
+ catch (const std::exception & Oops)
{
- LOGINFO("Recompression failed: %d", errorcode);
+ LOGWARNING("Recompression failed. %s", Oops.what());
return false;
}
- m_CompressedChunkData[0] = COMPRESSION_ZLIB;
- ASSERT(CompressedSize < static_cast<uLong>(std::numeric_limits<int>::max()));
- m_CompressedChunkDataSize = static_cast<int>(CompressedSize + 1);
- return true;
}
diff --git a/Tools/MCADefrag/MCADefrag.h b/Tools/MCADefrag/MCADefrag.h
index cddaef625..cc151d032 100644
--- a/Tools/MCADefrag/MCADefrag.h
+++ b/Tools/MCADefrag/MCADefrag.h
@@ -13,10 +13,18 @@
+#include "OSSupport/IsThread.h"
+#include "StringCompression.h"
+
+
+
+
+
class cMCADefrag
{
public:
+
enum
{
MAX_COMPRESSED_CHUNK_DATA_SIZE = (1 MiB),
@@ -33,6 +41,7 @@ public:
void Run(void);
protected:
+
/** A single thread processing MCA files from the queue */
class cThread :
public cIsThread
@@ -40,9 +49,11 @@ protected:
typedef cIsThread super;
public:
+
cThread(cMCADefrag & a_Parent);
protected:
+
/** The compression methods, as specified by the MCA compression method byte. */
enum
{
@@ -75,6 +86,12 @@ protected:
WriteChunk() tests this flag to decide whether to call Compress(). */
bool m_IsChunkUncompressed;
+ /** An instance of the compressor. */
+ Compression::Compressor m_Compressor;
+
+ /** An instance of the extractor. */
+ Compression::Extractor m_Extractor;
+
/** Processes the specified file. */
void ProcessFile(const AString & a_FileName);