Skip to content

Commit

Permalink
Utilities: Update Compression
Browse files Browse the repository at this point in the history
  • Loading branch information
HTRamsey committed Sep 19, 2024
1 parent 5b1b6aa commit d394ae0
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 61 deletions.
74 changes: 50 additions & 24 deletions src/Utilities/Compression/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,63 @@ find_package(Qt6 REQUIRED COMPONENTS Core)
qt_add_library(Compression STATIC
QGCLZMA.cc
QGCLZMA.h
QGCZip.cc
QGCZip.h
QGCZlib.cc
QGCZlib.h
)

target_link_libraries(Compression
PRIVATE
Qt6::CorePrivate
Utilities
PUBLIC
Qt6::Core
)

target_include_directories(Compression PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

include(FetchContent)

############### ZLIB

set(ZLIB_BUILD_EXAMPLES OFF CACHE INTERNAL "")
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "")
set(SKIP_INSTALL_FILES ON CACHE INTERNAL "")
set(SKIP_INSTALL_LIBRARIES ON CACHE INTERNAL "")
set(SKIP_INSTALL_HEADERS ON CACHE INTERNAL "")
set(SKIP_INSTALL_ALL ON CACHE INTERNAL "")
set(MINIMUM_ZLIB_VERSION 1.3)

FetchContent_Declare(zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.3.1
GIT_SHALLOW TRUE
)
if(NOT QGC_BUILD_DEPENDENCIES)
set(ZLIB_USE_STATIC_LIBS ON)
find_package(ZLIB ${MINIMUM_ZLIB_VERSION})
if(ZLIB_FOUND)
message(STATUS "Found ZLIB ${ZLIB_VERSION_STRING}")
target_link_libraries(Compression PRIVATE ZLIB::ZLIB)
else()
find_package(PkgConfig)
if(PkgConfig_FOUND)
pkg_check_modules(ZLIB IMPORTED_TARGET ZLIB>=${MINIMUM_ZLIB_VERSION})
if(ZLIB_FOUND)
message(STATUS "Found ZLIB ${ZLIB_VERSION}")
target_link_libraries(Joystick PRIVATE PkgConfig::ZLIB)
endif()
endif()
endif()
endif()

if(NOT ZLIB_FOUND)
set(ZLIB_BUILD_EXAMPLES OFF CACHE INTERNAL "")
set(SKIP_INSTALL_FILES ON CACHE INTERNAL "")
set(SKIP_INSTALL_LIBRARIES ON CACHE INTERNAL "")
set(SKIP_INSTALL_HEADERS ON CACHE INTERNAL "")
set(SKIP_INSTALL_ALL ON CACHE INTERNAL "")

FetchContent_Declare(zlib
GIT_REPOSITORY https://github.com/madler/zlib.git
GIT_TAG v1.3.1
GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(zlib)

target_link_libraries(Compression PRIVATE zlibstatic)
endif()

############### XZ

Expand All @@ -32,7 +69,7 @@ FetchContent_Declare(xz-embedded
GIT_SHALLOW TRUE
)

FetchContent_MakeAvailable(zlib xz-embedded)
FetchContent_MakeAvailable(xz-embedded)

qt_add_library(xz STATIC
${xz-embedded_SOURCE_DIR}/linux/include/linux/xz.h
Expand Down Expand Up @@ -61,15 +98,4 @@ target_compile_definitions(xz
XZ_USE_CRC64
)

###############

target_link_libraries(Compression
PRIVATE
zlibstatic
xz
Utilities
PUBLIC
Qt6::Core
)

target_include_directories(Compression PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Compression PRIVATE xz)
30 changes: 17 additions & 13 deletions src/Utilities/Compression/QGCLZMA.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,19 @@ QGC_LOGGING_CATEGORY(QGCLZMALog, "qgc.compression.qgclzma")

static std::once_flag crc_init;

bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decompressedFilename)
namespace QGCLZMA {

bool inflateLZMAFile(const QString &lzmaFilename, const QString &decompressedFilename)
{
QFile inputFile(lzmaFilename);
if (!inputFile.open(QIODevice::ReadOnly)) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: open input file failed" << lzmaFilename << inputFile.errorString();
qCWarning(QGCLZMALog) << "open input file failed" << lzmaFilename << inputFile.errorString();
return false;
}

QFile outputFile(decompressedFilename);
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: open input file failed" << outputFile.fileName() << outputFile.errorString();
qCWarning(QGCLZMALog) << "open input file failed" << outputFile.fileName() << outputFile.errorString();
return false;
}

Expand All @@ -44,7 +46,7 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp

xz_dec *s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
if (s == nullptr) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Memory allocation failed";
qCWarning(QGCLZMALog) << "Memory allocation failed";
return false;
}

Expand All @@ -71,7 +73,7 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
if (b.out_pos == sizeof(out)) {
size_t cBytesWritten = (size_t)outputFile.write((char*)out, static_cast<int>(b.out_pos));
if (cBytesWritten != b.out_pos) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
qCWarning(QGCLZMALog) << "output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto error;
}

Expand All @@ -82,13 +84,13 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
continue;

if (ret == XZ_UNSUPPORTED_CHECK) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Unsupported check; not verifying file integrity";
qCWarning(QGCLZMALog) << "Unsupported check; not verifying file integrity";
continue;
}

size_t cBytesWritten = (size_t)outputFile.write((char*)out, static_cast<int>(b.out_pos));
if (cBytesWritten != b.out_pos) {
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
qCWarning(QGCLZMALog) << "output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto error;
}

Expand All @@ -98,28 +100,28 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
return true;

case XZ_MEM_ERROR:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Memory allocation failed";
qCWarning(QGCLZMALog) << "Memory allocation failed";
goto error;

case XZ_MEMLIMIT_ERROR:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Memory usage limit reached";
qCWarning(QGCLZMALog) << "Memory usage limit reached";
goto error;

case XZ_FORMAT_ERROR:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Not a .xz file";
qCWarning(QGCLZMALog) << "Not a .xz file";
goto error;

case XZ_OPTIONS_ERROR:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Unsupported options in the .xz headers";
qCWarning(QGCLZMALog) << "Unsupported options in the .xz headers";
goto error;

case XZ_DATA_ERROR:
case XZ_BUF_ERROR:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: File is corrupt";
qCWarning(QGCLZMALog) << "File is corrupt";
goto error;

default:
qCWarning(QGCLZMALog) << "QGCLZMA::inflateLZMAFile: Bug!";
qCWarning(QGCLZMALog) << "Bug!";
goto error;
}
}
Expand All @@ -132,3 +134,5 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
return false;

}

} // namespace QGCLZMA
8 changes: 3 additions & 5 deletions src/Utilities/Compression/QGCLZMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

Q_DECLARE_LOGGING_CATEGORY(QGCLZMALog)

class QGCLZMA
{
public:
namespace QGCLZMA {
/// Decompresses the specified file to the specified directory
/// @param lzmaFilename Fully qualified path to lzma file
/// @param decompressedFilename Fully qualified path to for file to decompress to
static bool inflateLZMAFile(const QString& lzmaFilename, const QString& decompressedFilename);
};
bool inflateLZMAFile(const QString &lzmaFilename, const QString &decompressedFilename);
} // namespace QGCLZMA
97 changes: 97 additions & 0 deletions src/Utilities/Compression/QGCZip.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "QGCZip.h"
#include "QGCLoggingCategory.h"

#include <QtCore/QDir>
#include <QtCore/private/qzipreader_p.h>
#include <QtCore/private/qzipwriter_p.h>

QGC_LOGGING_CATEGORY(QGCZipLog, "qgc.utilities.compression.qgczip")

namespace QGCZip {

bool zipDirectory(const QString &directoryPath, const QString &zipFilePath)
{
QDir dir(directoryPath);
if (!dir.exists()) {
qCDebug(QGCZipLog) << "Directory does not exist:" << directoryPath;
return false;
}

QFile zipFile(zipFilePath);
if (!zipFile.open(QIODevice::WriteOnly)) {
qCDebug(QGCZipLog) << "Could not open zip file for writing:" << zipFilePath;
return false;
}

QZipWriter zipWriter(&zipFile);
zipWriter.setCompressionPolicy(QZipWriter::AutoCompress);

QStringList fileList = dir.entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::AllDirs, QDir::DirsFirst);

for (const QString &fileName : fileList) {
QString filePath = directoryPath + "/" + fileName;

if (QFileInfo(filePath).isDir()) {
zipWriter.addDirectory(fileName);
} else {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
zipWriter.addFile(fileName, file.readAll());
file.close();
} else {
qCDebug(QGCZipLog) << "Could not open file for reading:" << filePath;
return false;
}
}
}

zipWriter.close();
return true;
}

bool unzipFile(const QString &zipFilePath, const QString &outputDirectoryPath)
{
QDir outputDir(outputDirectoryPath);
if (!outputDir.exists()) {
if (!outputDir.mkpath(outputDirectoryPath)) {
qCDebug(QGCZipLog) << "Failed to create output directory:" << outputDirectoryPath;
return false;
}
}

QFile zipFile(zipFilePath);
if (!zipFile.open(QIODevice::ReadOnly)) {
qCDebug(QGCZipLog) << "Could not open zip file:" << zipFilePath;
return false;
}

QZipReader zipReader(&zipFile);
if (!zipReader.isReadable()) {
qCDebug(QGCZipLog) << "Could not read zip file:" << zipFilePath;
return false;
}

const QList<QZipReader::FileInfo> allFiles = zipReader.fileInfoList();

for (const QZipReader::FileInfo &fileInfo : allFiles) {
QString filePath = outputDirectoryPath + "/" + fileInfo.filePath;

if (fileInfo.isDir) {
QDir().mkpath(filePath);
} else if (fileInfo.isFile) {
QFile outFile(filePath);
if (outFile.open(QIODevice::WriteOnly)) {
outFile.write(zipReader.fileData(fileInfo.filePath));
outFile.close();
} else {
qDebug() << "Could not open file for writing:" << filePath;
return false;
}
}
}

zipReader.close();
return true;
}

} // namespace QGCZip
13 changes: 13 additions & 0 deletions src/Utilities/Compression/QGCZip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <QtCore/QLoggingCategory>

Q_DECLARE_LOGGING_CATEGORY(QGCZipLog)

namespace QGCZip {
/// Method to zip files in a given directory
bool zipDirectory(const QString &directoryPath, const QString &zipFilePath);

/// Method to unzip files to a given directory
bool unzipFile(const QString &zipFilePath, const QString &outputDirectoryPath);
} // namespace QGCZip
16 changes: 10 additions & 6 deletions src/Utilities/Compression/QGCZlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

QGC_LOGGING_CATEGORY(QGCZlibLog, "qgc.compression.qgczlib")

bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& decompressedFilename)
namespace QGCZlib {

bool inflateGzipFile(const QString &gzippedFileName, const QString &decompressedFilename)
{
bool success = true;
int ret;
Expand All @@ -28,13 +30,13 @@ bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& dec

QFile inputFile(gzippedFileName);
if (!inputFile.open(QIODevice::ReadOnly)) {
qCWarning(QGCZlibLog) << "QGCZlib::inflateGzipFile: open input file failed" << gzippedFileName << inputFile.errorString();
qCWarning(QGCZlibLog) << "open input file failed" << gzippedFileName << inputFile.errorString();
return false;
}

QFile outputFile(decompressedFilename);
if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qCWarning(QGCZlibLog) << "QGCZlib::inflateGzipFile: open input file failed" << outputFile.fileName() << outputFile.errorString();
qCWarning(QGCZlibLog) << "open input file failed" << outputFile.fileName() << outputFile.errorString();
return false;
}

Expand All @@ -46,7 +48,7 @@ bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& dec

ret = inflateInit2(&strm, 16+MAX_WBITS);
if (ret != Z_OK) {
qCWarning(QGCZlibLog) << "QGCZlib::inflateGzipFile: inflateInit2 failed:" << ret;
qCWarning(QGCZlibLog) << "inflateInit2 failed:" << ret;
goto Error;
}

Expand All @@ -63,14 +65,14 @@ bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& dec

ret = inflate(&strm, Z_NO_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) {
qCWarning(QGCZlibLog) << "QGCZlib::inflateGzipFile: inflate failed:" << ret;
qCWarning(QGCZlibLog) << "inflate failed:" << ret;
goto Error;
}

unsigned cBytesInflated = cBuffer - strm.avail_out;
qint64 cBytesWritten = outputFile.write((char*)outputBuffer, static_cast<int>(cBytesInflated));
if (cBytesWritten != cBytesInflated) {
qCWarning(QGCZlibLog) << "QGCZlib::inflateGzipFile: output file write failed:" << outputFile.fileName() << outputFile.errorString();
qCWarning(QGCZlibLog) << "output file write failed:" << outputFile.fileName() << outputFile.errorString();
goto Error;

}
Expand All @@ -85,3 +87,5 @@ bool QGCZlib::inflateGzipFile(const QString& gzippedFileName, const QString& dec
success = false;
goto Out;
}

} // namespace QGCZlib
8 changes: 3 additions & 5 deletions src/Utilities/Compression/QGCZlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@

Q_DECLARE_LOGGING_CATEGORY(QGCZlibLog)

class QGCZlib
{
public:
namespace QGCZlib {
/// Decompresses the specified file to the specified directory
/// @param gzipFilename Fully qualified path to gzip file
/// @param decompressedFilename Fully qualified path to for file to decompress to
static bool inflateGzipFile(const QString& gzippedFileName, const QString& decompressedFilename);
};
bool inflateGzipFile(const QString &gzippedFileName, const QString &decompressedFilename);
} // namespace QGCZlib
Loading

0 comments on commit d394ae0

Please sign in to comment.