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 6595038
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 95 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)
50 changes: 23 additions & 27 deletions src/Utilities/Compression/QGCLZMA.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "QGCLoggingCategory.h"

#include <QtCore/QFile>
#include <QtCore/QtDebug>

#include <mutex>

Expand All @@ -21,34 +20,34 @@ 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;
}


std::call_once(crc_init, []() {
xz_crc32_init();
xz_crc64_init();
});


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

const int buf_size = 4 * 1024;
constexpr int buf_size = 4 * 1024;
uint8_t in[buf_size];
uint8_t out[buf_size];

Expand All @@ -69,57 +68,52 @@ bool QGCLZMA::inflateLZMAFile(const QString& lzmaFilename, const QString& decomp
xz_ret ret = xz_dec_run(s, &b);

if (b.out_pos == sizeof(out)) {
size_t cBytesWritten = (size_t)outputFile.write((char*)out, static_cast<int>(b.out_pos));
const size_t cBytesWritten = static_cast<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;
}

b.out_pos = 0;
}

if (ret == XZ_OK)
if (ret == XZ_OK) {
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));
const size_t cBytesWritten = static_cast<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;
}

switch (ret) {
case XZ_STREAM_END:
xz_dec_end(s);
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 +126,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
Loading

0 comments on commit 6595038

Please sign in to comment.