From 5dc773579b4afeb818cae8b9ecc0db791e36c1e9 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Tue, 25 Aug 2015 02:09:18 -0400 Subject: [PATCH] Added support for reading gzipped glabels files. - Use zlib to uncompress input --- CMakeLists.txt | 1 + glabels/CMakeLists.txt | 2 ++ glabels/XmlLabel.cpp | 72 ++++++++++++++++++++++++++++++++++++++++-- glabels/XmlLabel.h | 1 + 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ddf28c4..9a4f1ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set (Unique_Package_Name ${Package_Name}-${API_Version}) find_package(Qt4 4.8.4 REQUIRED QtCore QtGui QtXml) +find_package(ZLIB REQUIRED) add_definitions (-g) diff --git a/glabels/CMakeLists.txt b/glabels/CMakeLists.txt index 175f6fd..eacfc69 100644 --- a/glabels/CMakeLists.txt +++ b/glabels/CMakeLists.txt @@ -93,6 +93,7 @@ include (${QT_USE_FILE}) include_directories ( + ${ZLIB_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${glabels_qt_SOURCE_DIR} @@ -107,6 +108,7 @@ add_executable (glabels-qt ${glabels_sources} ${glabels_moc_sources} ${glabels_q target_link_libraries (glabels-qt libglabels ${QT_LIBRARIES} + ${ZLIB_LIBRARIES} ) diff --git a/glabels/XmlLabel.cpp b/glabels/XmlLabel.cpp index 2fbb1fb..1dc43ca 100644 --- a/glabels/XmlLabel.cpp +++ b/glabels/XmlLabel.cpp @@ -31,6 +31,8 @@ #include "libglabels/XmlUtil.h" #include +#include +#include #include @@ -38,26 +40,41 @@ glabels::LabelModel* glabels::XmlLabel::readFile( const QString& fileName ) { QFile file( fileName ); - if ( !file.open( QFile::ReadOnly | QFile::Text) ) + if ( !file.open( QFile::ReadOnly ) ) { qWarning() << "Error: Cannot read file " << qPrintable(fileName) << ": " << file.errorString(); return 0; } - QDomDocument doc; + bool success; QString errorString; int errorLine; int errorColumn; - if ( !doc.setContent( &file, false, &errorString, &errorLine, &errorColumn ) ) + QByteArray rawData = file.readAll(); + if ( ((rawData[0]&0xFF) == 0x1F) && ((rawData[1]&0xFF) == 0x8b) ) // gzip magic number 0x1F, 0x8B + { + // gzip compressed format + QByteArray unzippedData; + gunzip( rawData, unzippedData ); + success = doc.setContent( unzippedData, false, &errorString, &errorLine, &errorColumn ); + } + else + { + // plain text + success = doc.setContent( rawData, false, &errorString, &errorLine, &errorColumn ); + } + + if ( !success ) { qWarning() << "Error: Parse error at line " << errorLine << "column " << errorColumn << ": " << errorString; return 0; } + QDomElement root = doc.documentElement(); if ( root.tagName() != "Glabels-document" ) @@ -124,6 +141,55 @@ void glabels::XmlLabel::writeBuffer( const LabelModel* label, QString& buffer ) } +void glabels::XmlLabel::gunzip( const QByteArray& data, QByteArray& result ) +{ + result.clear(); + + if (data.size() <= 4) { + qWarning("XmlLabel::gunzip: Input data is truncated"); + return; + } + + // setup stream for inflate() + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = data.size(); + strm.next_in = (Bytef*)(data.data()); + + int ret = inflateInit2(&strm, MAX_WBITS + 16); // gzip decoding + if (ret != Z_OK) + { + return; + } + + static const int CHUNK_SIZE = 1024; + char out[CHUNK_SIZE]; + + // run inflate(), one chunk at a time + do { + strm.avail_out = CHUNK_SIZE; + strm.next_out = (Bytef*)(out); + + ret = inflate(&strm, Z_NO_FLUSH); + Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered + + if ( (ret == Z_NEED_DICT) || (ret == Z_DATA_ERROR) || (ret == Z_MEM_ERROR) ) + { + // clean up + inflateEnd(&strm); + return; + } + + result.append(out, CHUNK_SIZE - strm.avail_out); + } while (strm.avail_out == 0); + + // clean up + inflateEnd(&strm); +} + + glabels::LabelModel* glabels::XmlLabel::parseRootNode( const QDomElement &node ) { using namespace libglabels; diff --git a/glabels/XmlLabel.h b/glabels/XmlLabel.h index 2e4669b..b432fe2 100644 --- a/glabels/XmlLabel.h +++ b/glabels/XmlLabel.h @@ -52,6 +52,7 @@ namespace glabels static void writeBuffer( const LabelModel* label, QString& buffer ); private: + static void gunzip( const QByteArray& gzippedData, QByteArray& data ); static LabelModel* parseRootNode( const QDomElement &node ); static void parseObjectsNode( const QDomElement &node, LabelModel* label ); static void parseObjectBoxNode( const QDomElement &node, LabelModel* label );