diff --git a/RagePhoto.cpp b/RagePhoto.cpp index 5ea3c11..5575cc1 100644 --- a/RagePhoto.cpp +++ b/RagePhoto.cpp @@ -23,6 +23,10 @@ #if QT_VERSION < 0x060000 #include #endif +#ifdef RAGEPHOTO_BENCHMARK +#include +#include +#endif RagePhoto::RagePhoto() { @@ -83,6 +87,10 @@ bool RagePhoto::load() QBuffer dataBuffer(&p_fileData); dataBuffer.open(QIODevice::ReadOnly); +#ifdef RAGEPHOTO_BENCHMARK + auto benchmark_parse_start = std::chrono::high_resolution_clock::now(); +#endif + char uInt32Buffer[4]; qint64 size = dataBuffer.read(uInt32Buffer, 4); if (size != 4) @@ -90,12 +98,9 @@ bool RagePhoto::load() quint32 format = charToUInt32LE(uInt32Buffer); if (format == static_cast(PhotoFormat::GTA5)) { - char *photoHeader = static_cast(malloc(256)); - if (!photoHeader) - return false; + char photoHeader[256]; size = dataBuffer.read(photoHeader, 256); if (size != 256) { - free(photoHeader); return false; } for (const QChar &photoChar : utf16LEToString(photoHeader, 256)) { @@ -103,7 +108,6 @@ bool RagePhoto::load() break; p_photoString += photoChar; } - free(photoHeader); size = dataBuffer.read(uInt32Buffer, 4); if (size != 4) @@ -209,11 +213,12 @@ bool RagePhoto::load() free(titlBytes); return false; } - for (const QChar &titlChar : QString::fromUtf8(titlBytes, p_titlBuffer)) { - if (titlChar.isNull()) + quint32 i; + for (i = 0; i != p_titlBuffer; i++) { + if (titlBytes[i] == '\x00') break; - p_titleString += titlChar; } + p_titleString = QString::fromUtf8(titlBytes, i); free(titlBytes); dataBuffer.seek(p_descOffset + 264); @@ -236,11 +241,11 @@ bool RagePhoto::load() free(descBytes); return false; } - for (const QChar &descChar : QString::fromUtf8(descBytes, p_descBuffer)) { - if (descChar.isNull()) + for (i = 0; i != p_descBuffer; i++) { + if (descBytes[i] == '\x00') break; - p_descriptionString += descChar; } + p_descriptionString = QString::fromUtf8(descBytes, i); free(descBytes); dataBuffer.seek(p_endOfFile + 260); @@ -250,6 +255,17 @@ bool RagePhoto::load() if (strncmp(markerBuffer, "JEND", 4) != 0) return false; +#ifdef RAGEPHOTO_BENCHMARK + auto benchmark_parse_end = std::chrono::high_resolution_clock::now(); + auto benchmark_ns = std::chrono::duration_cast(benchmark_parse_end - benchmark_parse_start); + if (p_inputMode == 1) { + QTextStream(stdout) << QFileInfo(p_filePath).fileName() << ": " << static_cast(benchmark_ns.count()) << "ns" << Qt::endl; + } + else { + QTextStream(stdout) << "PGTA5" << p_jsonObject.value("uid").toInt() << ": " << static_cast(benchmark_ns.count()) << "ns" << Qt::endl; + } +#endif + if (p_photoFormat != PhotoFormat::G5EX) p_photoFormat = PhotoFormat::GTA5; @@ -404,6 +420,17 @@ bool RagePhoto::load() return false; p_endOfFile = charToUInt32LE(uInt32Buffer); +#ifdef RAGEPHOTO_BENCHMARK + auto benchmark_parse_end = std::chrono::high_resolution_clock::now(); + auto benchmark_ns = std::chrono::duration_cast(benchmark_parse_end - benchmark_parse_start); + if (p_inputMode == 1) { + QTextStream(stdout) << QFileInfo(p_filePath).fileName() << ": " << static_cast(benchmark_ns.count()) << "ns" << Qt::endl; + } + else { + QTextStream(stdout) << "PGTA5" << p_jsonObject.value("uid").toInt() << ": " << static_cast(benchmark_ns.count()) << "ns" << Qt::endl; + } +#endif + p_photoFormat = PhotoFormat::G5EX; p_fileData.clear(); @@ -421,12 +448,12 @@ bool RagePhoto::load() else if (format == static_cast(ExportFormat::G5E1P)) { #if QT_VERSION >= 0x050A00 size = dataBuffer.skip(1); -#else - QByteArray skipData = dataBuffer.read(1); - size = skipData.size(); -#endif if (size != 1) return false; +#else + if (!dataBuffer.seek(dataBuffer.pos() + 1)) + return false; +#endif char length[1]; size = dataBuffer.read(length, 1); @@ -436,12 +463,12 @@ bool RagePhoto::load() #if QT_VERSION >= 0x050A00 size = dataBuffer.skip(i_length); -#else - skipData = dataBuffer.read(i_length); - size = skipData.size(); -#endif if (size != i_length) return false; +#else + if (!dataBuffer.seek(dataBuffer.pos() + i_length)) + return false; +#endif p_photoFormat = PhotoFormat::G5EX; p_fileData = qUncompress(dataBuffer.readAll()); @@ -613,67 +640,67 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) if (photoFormat == PhotoFormat::G5EX) { char uInt32Buffer[4]; quint32 format = static_cast(PhotoFormat::G5EX); - uInt32ToCharLE(&format, uInt32Buffer); + uInt32ToCharLE(format, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); format = static_cast(ExportFormat::G5E3P); - uInt32ToCharLE(&format, uInt32Buffer); + uInt32ToCharLE(format, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); QByteArray compressedData = qCompress(p_photoString.toUtf8(), 9); quint32 compressedSize = compressedData.size(); - uInt32ToCharLE(&compressedSize, uInt32Buffer); + uInt32ToCharLE(compressedSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(compressedData); - uInt32ToCharLE(&p_headerSum, uInt32Buffer); + uInt32ToCharLE(p_headerSum, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_photoBuffer, uInt32Buffer); + uInt32ToCharLE(p_photoBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); compressedData = qCompress(p_photoData, 9); compressedSize = compressedData.size(); - uInt32ToCharLE(&compressedSize, uInt32Buffer); + uInt32ToCharLE(compressedSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(compressedData); - uInt32ToCharLE(&p_jsonOffset, uInt32Buffer); + uInt32ToCharLE(p_jsonOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_jsonBuffer, uInt32Buffer); + uInt32ToCharLE(p_jsonBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); compressedData = qCompress(p_jsonData, 9); compressedSize = compressedData.size(); - uInt32ToCharLE(&compressedSize, uInt32Buffer); + uInt32ToCharLE(compressedSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(compressedData); - uInt32ToCharLE(&p_titlOffset, uInt32Buffer); + uInt32ToCharLE(p_titlOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_titlBuffer, uInt32Buffer); + uInt32ToCharLE(p_titlBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); compressedData = qCompress(p_titleString.toUtf8(), 9); compressedSize = compressedData.size(); - uInt32ToCharLE(&compressedSize, uInt32Buffer); + uInt32ToCharLE(compressedSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(compressedData); - uInt32ToCharLE(&p_descOffset, uInt32Buffer); + uInt32ToCharLE(p_descOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_descBuffer, uInt32Buffer); + uInt32ToCharLE(p_descBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); compressedData = qCompress(p_descriptionString.toUtf8(), 9); compressedSize = compressedData.size(); - uInt32ToCharLE(&compressedSize, uInt32Buffer); + uInt32ToCharLE(compressedSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(compressedData); - uInt32ToCharLE(&p_endOfFile, uInt32Buffer); + uInt32ToCharLE(p_endOfFile, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); #if QT_VERSION >= 0x050000 @@ -683,11 +710,11 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) else if (photoFormat == PhotoFormat::GTA5) { char uInt32Buffer[4]; quint32 format = static_cast(PhotoFormat::GTA5); - uInt32ToCharLE(&format, uInt32Buffer); + uInt32ToCharLE(format, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); QByteArray photoHeader = stringToUtf16LE(p_photoString); - if (photoHeader.left(2) == "\xFF\xFE") { + if (photoHeader.startsWith("\xFF\xFE")) { photoHeader.remove(0, 2); } qint64 photoHeaderSize = photoHeader.size(); @@ -700,28 +727,28 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) ioDevice->write("\x00", 1); } - uInt32ToCharLE(&p_headerSum, uInt32Buffer); + uInt32ToCharLE(p_headerSum, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_endOfFile, uInt32Buffer); + uInt32ToCharLE(p_endOfFile, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_jsonOffset, uInt32Buffer); + uInt32ToCharLE(p_jsonOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_titlOffset, uInt32Buffer); + uInt32ToCharLE(p_titlOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); - uInt32ToCharLE(&p_descOffset, uInt32Buffer); + uInt32ToCharLE(p_descOffset, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write("JPEG", 4); - uInt32ToCharLE(&p_photoBuffer, uInt32Buffer); + uInt32ToCharLE(p_photoBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); quint32 t_photoSize = p_photoData.size(); - uInt32ToCharLE(&t_photoSize, uInt32Buffer); + uInt32ToCharLE(t_photoSize, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); ioDevice->write(p_photoData); @@ -732,7 +759,7 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) ioDevice->seek(p_jsonOffset + 264); ioDevice->write("JSON", 4); - uInt32ToCharLE(&p_jsonBuffer, uInt32Buffer); + uInt32ToCharLE(p_jsonBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); qint64 dataSize = p_jsonData.size(); @@ -744,7 +771,7 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) ioDevice->seek(p_titlOffset + 264); ioDevice->write("TITL", 4); - uInt32ToCharLE(&p_titlBuffer, uInt32Buffer); + uInt32ToCharLE(p_titlBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); QByteArray data = p_titleString.toUtf8(); @@ -757,7 +784,7 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) ioDevice->seek(p_descOffset + 264); ioDevice->write("DESC", 4); - uInt32ToCharLE(&p_descBuffer, uInt32Buffer); + uInt32ToCharLE(p_descBuffer, uInt32Buffer); ioDevice->write(uInt32Buffer, 4); data = p_descriptionString.toUtf8(); @@ -769,10 +796,6 @@ void RagePhoto::save(QIODevice *ioDevice, PhotoFormat photoFormat) ioDevice->seek(p_endOfFile + 260); ioDevice->write("JEND", 4); - -#if QT_VERSION >= 0x050000 - ioDevice->aboutToClose(); -#endif } } @@ -786,36 +809,36 @@ RagePhoto* RagePhoto::loadFile(const QString &filePath) quint32 RagePhoto::charToUInt32BE(char *x) { return (static_cast(x[0]) << 24 | - static_cast(x[1]) << 16 | - static_cast(x[2]) << 8 | - static_cast(x[3])); + static_cast(x[1]) << 16 | + static_cast(x[2]) << 8 | + static_cast(x[3])); } quint32 RagePhoto::charToUInt32LE(char *x) { return (static_cast(x[3]) << 24 | - static_cast(x[2]) << 16 | - static_cast(x[1]) << 8 | - static_cast(x[0])); + static_cast(x[2]) << 16 | + static_cast(x[1]) << 8 | + static_cast(x[0])); } -void RagePhoto::uInt32ToCharBE(quint32 *x, char *y) +void RagePhoto::uInt32ToCharBE(quint32 x, char *y) { - y[0] = (*x >> 24) & 0xFF; - y[1] = (*x >> 16) & 0xFF; - y[2] = (*x >> 8) & 0xFF; - y[3] = (*x) & 0xFF; + y[0] = x >> 24; + y[1] = x >> 16; + y[2] = x >> 8; + y[3] = x; } -void RagePhoto::uInt32ToCharLE(quint32 *x, char *y) +void RagePhoto::uInt32ToCharLE(quint32 x, char *y) { - y[0] = (*x) & 0xFF; - y[1] = (*x >> 8) & 0xFF; - y[2] = (*x >> 16) & 0xFF; - y[3] = (*x >> 24) & 0xFF; + y[0] = x; + y[1] = x >> 8; + y[2] = x >> 16; + y[3] = x >> 24; } -QByteArray RagePhoto::stringToUtf16LE(const QString &string) +const QByteArray RagePhoto::stringToUtf16LE(const QString &string) { #if QT_VERSION >= 0x060000 QStringEncoder stringEncoder = QStringEncoder(QStringEncoder::Utf16LE); @@ -825,7 +848,7 @@ QByteArray RagePhoto::stringToUtf16LE(const QString &string) #endif } -QString RagePhoto::utf16LEToString(const QByteArray &data) +const QString RagePhoto::utf16LEToString(const QByteArray &data) { #if QT_VERSION >= 0x060000 QStringDecoder stringDecoder = QStringDecoder(QStringDecoder::Utf16LE); @@ -835,7 +858,7 @@ QString RagePhoto::utf16LEToString(const QByteArray &data) #endif } -QString RagePhoto::utf16LEToString(const char *data, int size) +const QString RagePhoto::utf16LEToString(const char *data, int size) { #if QT_VERSION >= 0x060000 QStringDecoder stringDecoder = QStringDecoder(QStringDecoder::Utf16LE); diff --git a/RagePhoto.h b/RagePhoto.h index 5ccac55..4f7a5ba 100644 --- a/RagePhoto.h +++ b/RagePhoto.h @@ -79,11 +79,11 @@ public: private: inline quint32 charToUInt32BE(char *x); inline quint32 charToUInt32LE(char *x); - inline void uInt32ToCharBE(quint32 *x, char *y); - inline void uInt32ToCharLE(quint32 *x, char *y); - inline QByteArray stringToUtf16LE(const QString &string); - inline QString utf16LEToString(const QByteArray &data); - inline QString utf16LEToString(const char *data, int size); + inline void uInt32ToCharBE(quint32 x, char *y); + inline void uInt32ToCharLE(quint32 x, char *y); + inline const QByteArray stringToUtf16LE(const QString &string); + inline const QString utf16LEToString(const QByteArray &data); + inline const QString utf16LEToString(const char *data, int size); PhotoFormat p_photoFormat; QJsonObject p_jsonObject; QByteArray p_fileData;