add Win32 API Unicode converter, other small changes
Qt Example: add file.close() (consistency between GTK example) RagePhoto: saveFile() checks for good(), more data() -> c_str()
This commit is contained in:
parent
85ab850895
commit
05890541dc
6 changed files with 122 additions and 21 deletions
|
@ -47,6 +47,17 @@ else()
|
||||||
message("-- Testing iconv - no")
|
message("-- Testing iconv - no")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
message("-- Testing wincvt")
|
||||||
|
try_run(WINCVT_RUN WINCVT_COMPILE ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/tests/WincvtTest.cpp)
|
||||||
|
if (WINCVT_COMPILE AND WINCVT_RUN EQUAL 0)
|
||||||
|
list(APPEND LIBRAGEPHOTO_DEFINES
|
||||||
|
WINCVT_COMPATIBLE
|
||||||
|
)
|
||||||
|
message("-- Testing wincvt - yes")
|
||||||
|
else()
|
||||||
|
message("-- Testing wincvt - no")
|
||||||
|
endif()
|
||||||
|
|
||||||
# RagePhoto Source files
|
# RagePhoto Source files
|
||||||
set(RAGEPHOTO_HEADERS
|
set(RAGEPHOTO_HEADERS
|
||||||
src/RagePhoto.h
|
src/RagePhoto.h
|
||||||
|
|
|
@ -34,6 +34,7 @@ bool readPhotoFile(const QString &filename, QMainWindow *mainWindow, QLabel *pho
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
const QByteArray fileData = file.readAll();
|
const QByteArray fileData = file.readAll();
|
||||||
|
file.close();
|
||||||
RagePhoto ragePhoto;
|
RagePhoto ragePhoto;
|
||||||
const bool loaded = ragePhoto.load(fileData.data(), static_cast<size_t>(fileData.size()));
|
const bool loaded = ragePhoto.load(fileData.data(), static_cast<size_t>(fileData.size()));
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CODECVT_COMPATIBLE
|
#if defined WINCVT_COMPATIBLE
|
||||||
|
#include <stringapiset.h>
|
||||||
|
#elif defined CODECVT_COMPATIBLE
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#elif defined ICONV_COMPATIBLE
|
#elif defined ICONV_COMPATIBLE
|
||||||
|
@ -85,7 +87,7 @@ bool RagePhoto::load(const char *data, size_t length)
|
||||||
m_data.photoFormat = charToUInt32LE(uInt32Buffer);
|
m_data.photoFormat = charToUInt32LE(uInt32Buffer);
|
||||||
#endif
|
#endif
|
||||||
if (m_data.photoFormat == PhotoFormat::GTA5 || m_data.photoFormat == PhotoFormat::RDR2) {
|
if (m_data.photoFormat == PhotoFormat::GTA5 || m_data.photoFormat == PhotoFormat::RDR2) {
|
||||||
#if defined CODECVT_COMPATIBLE || defined ICONV_COMPATIBLE
|
#if defined WINCVT_COMPATIBLE || defined CODECVT_COMPATIBLE || defined ICONV_COMPATIBLE
|
||||||
char photoHeader[256];
|
char photoHeader[256];
|
||||||
size = readBuffer(data, photoHeader, &pos, 256, length);
|
size = readBuffer(data, photoHeader, &pos, 256, length);
|
||||||
if (size != 256) {
|
if (size != 256) {
|
||||||
|
@ -93,9 +95,21 @@ bool RagePhoto::load(const char *data, size_t length)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CODECVT_COMPATIBLE
|
#if defined WINCVT_COMPATIBLE
|
||||||
|
char photoHeader_string[256];
|
||||||
|
const int converted = WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast<wchar_t*>(photoHeader), -1, photoHeader_string, 256, NULL, NULL);
|
||||||
|
if (converted == 0) {
|
||||||
|
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_data.header = std::string(photoHeader_string);
|
||||||
|
#elif defined CODECVT_COMPATIBLE
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||||
m_data.header = convert.to_bytes(reinterpret_cast<char16_t*>(photoHeader));
|
m_data.header = convert.to_bytes(reinterpret_cast<char16_t*>(photoHeader));
|
||||||
|
if (convert.converted() == 0) {
|
||||||
|
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#elif defined ICONV_COMPATIBLE
|
#elif defined ICONV_COMPATIBLE
|
||||||
iconv_t iconv_in = iconv_open("UTF-8", "UTF-16LE");
|
iconv_t iconv_in = iconv_open("UTF-8", "UTF-16LE");
|
||||||
if (iconv_in == (iconv_t)-1) {
|
if (iconv_in == (iconv_t)-1) {
|
||||||
|
@ -465,17 +479,28 @@ const char* RagePhoto::version()
|
||||||
bool RagePhoto::save(char *data, uint32_t photoFormat)
|
bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
{
|
{
|
||||||
if (photoFormat == PhotoFormat::GTA5 || photoFormat == PhotoFormat::RDR2) {
|
if (photoFormat == PhotoFormat::GTA5 || photoFormat == PhotoFormat::RDR2) {
|
||||||
#if defined CODECVT_COMPATIBLE || defined ICONV_COMPATIBLE
|
#if defined WINCVT_COMPATIBLE || defined CODECVT_COMPATIBLE || defined ICONV_COMPATIBLE
|
||||||
#ifdef CODECVT_COMPATIBLE
|
#if defined WINCVT_COMPATIBLE
|
||||||
|
char photoHeader[256]{};
|
||||||
|
const int converted = MultiByteToWideChar(CP_UTF8, 0, m_data.header.data(), m_data.header.size(), reinterpret_cast<wchar_t*>(photoHeader), 256 / sizeof(wchar_t));
|
||||||
|
if (converted == 0) {
|
||||||
|
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size_t photoHeader_size = 256;
|
||||||
|
#elif defined CODECVT_COMPATIBLE
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||||
std::u16string photoHeader_string = convert.from_bytes(m_data.header);
|
std::u16string photoHeader_string = convert.from_bytes(m_data.header);
|
||||||
|
if (convert.converted() == 0) {
|
||||||
|
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const size_t photoHeader_size = photoHeader_string.size() * 2;
|
const size_t photoHeader_size = photoHeader_string.size() * 2;
|
||||||
if (photoHeader_size > 256) {
|
if (photoHeader_size > 256) {
|
||||||
m_data.error = static_cast<uint8_t>(Error::HeaderBufferTight); // 34
|
m_data.error = static_cast<uint8_t>(Error::HeaderBufferTight); // 34
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char photoHeader[256];
|
const char *photoHeader = reinterpret_cast<const char*>(photoHeader_string.data());
|
||||||
memcpy(photoHeader, photoHeader_string.data(), photoHeader_size);
|
|
||||||
#elif defined ICONV_COMPATIBLE
|
#elif defined ICONV_COMPATIBLE
|
||||||
iconv_t iconv_in = iconv_open("UTF-16LE", "UTF-8");
|
iconv_t iconv_in = iconv_open("UTF-16LE", "UTF-8");
|
||||||
if (iconv_in == (iconv_t)-1) {
|
if (iconv_in == (iconv_t)-1) {
|
||||||
|
@ -484,7 +509,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
}
|
}
|
||||||
char photoHeader_string[256];
|
char photoHeader_string[256];
|
||||||
memcpy(photoHeader_string, m_data.header.data(), m_data.header.size());
|
memcpy(photoHeader_string, m_data.header.data(), m_data.header.size());
|
||||||
char photoHeader[256];
|
char photoHeader[256]{};
|
||||||
size_t src_s = m_data.header.size();
|
size_t src_s = m_data.header.size();
|
||||||
size_t dst_s = sizeof(photoHeader);
|
size_t dst_s = sizeof(photoHeader);
|
||||||
char *src = photoHeader_string;
|
char *src = photoHeader_string;
|
||||||
|
@ -495,11 +520,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
m_data.error = static_cast<uint8_t>(Error::UnicodeHeaderError); // 5
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const size_t photoHeader_size = m_data.header.size() * 2;
|
const size_t photoHeader_size = 256;
|
||||||
if (photoHeader_size > 256) {
|
|
||||||
m_data.error = static_cast<uint8_t>(Error::HeaderBufferTight); // 34
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_data.photoSize > m_data.photoBuffer) {
|
if (m_data.photoSize > m_data.photoBuffer) {
|
||||||
|
@ -614,7 +635,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
#endif
|
#endif
|
||||||
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
||||||
|
|
||||||
writeBuffer(m_data.json.data(), data, &pos, length, jsonString_size);
|
writeBuffer(m_data.json.c_str(), data, &pos, length, jsonString_size);
|
||||||
for (size_t i = jsonString_size; i < m_data.jsonBuffer; i++) {
|
for (size_t i = jsonString_size; i < m_data.jsonBuffer; i++) {
|
||||||
writeBuffer("\0", data, &pos, length, 1);
|
writeBuffer("\0", data, &pos, length, 1);
|
||||||
}
|
}
|
||||||
|
@ -629,7 +650,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
#endif
|
#endif
|
||||||
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
||||||
|
|
||||||
writeBuffer(m_data.title.data(), data, &pos, length, titlString_size);
|
writeBuffer(m_data.title.c_str(), data, &pos, length, titlString_size);
|
||||||
for (size_t i = titlString_size; i < m_data.titlBuffer; i++) {
|
for (size_t i = titlString_size; i < m_data.titlBuffer; i++) {
|
||||||
writeBuffer("\0", data, &pos, length, 1);
|
writeBuffer("\0", data, &pos, length, 1);
|
||||||
}
|
}
|
||||||
|
@ -644,7 +665,7 @@ bool RagePhoto::save(char *data, uint32_t photoFormat)
|
||||||
#endif
|
#endif
|
||||||
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
writeBuffer(uInt32Buffer, data, &pos, length, 4);
|
||||||
|
|
||||||
writeBuffer(m_data.description.data(), data, &pos, length, descString_size);
|
writeBuffer(m_data.description.c_str(), data, &pos, length, descString_size);
|
||||||
for (size_t i = descString_size; i < m_data.descBuffer; i++) {
|
for (size_t i = descString_size; i < m_data.descBuffer; i++) {
|
||||||
writeBuffer("\0", data, &pos, length, 1);
|
writeBuffer("\0", data, &pos, length, 1);
|
||||||
}
|
}
|
||||||
|
@ -708,8 +729,9 @@ bool RagePhoto::saveFile(const std::string &filename, uint32_t photoFormat)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ofs << sdata;
|
ofs << sdata;
|
||||||
|
ok = ofs.good();
|
||||||
ofs.close();
|
ofs.close();
|
||||||
return true;
|
return ok;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -59,5 +59,8 @@ int main(int argc, char *argv[])
|
||||||
};
|
};
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||||
std::string photoString = convert.to_bytes(reinterpret_cast<char16_t*>(photoHeader));
|
std::string photoString = convert.to_bytes(reinterpret_cast<char16_t*>(photoHeader));
|
||||||
|
if (convert.converted() == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return strcmp(photoString.c_str(), "PHOTO - 02/01/17 08:42:44");
|
return strcmp(photoString.c_str(), "PHOTO - 02/01/17 08:42:44");
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,18 +56,18 @@ int main(int argc, char *argv[])
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
char photoString[256];
|
char photoHeader_string[256];
|
||||||
iconv_t iconv_in = iconv_open("UTF-8", "UTF-16LE");
|
iconv_t iconv_in = iconv_open("UTF-8", "UTF-16LE");
|
||||||
if (iconv_in == (iconv_t)-1)
|
if (iconv_in == (iconv_t)-1)
|
||||||
return -1;
|
return -1;
|
||||||
size_t src_s = sizeof(photoHeader);
|
size_t src_s = sizeof(photoHeader);
|
||||||
size_t dst_s = sizeof(photoString);
|
size_t dst_s = sizeof(photoHeader_string);
|
||||||
char *src = photoHeader;
|
char *src = photoHeader;
|
||||||
char *dst = photoString;
|
char *dst = photoHeader_string;
|
||||||
const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s);
|
const size_t ret = iconv(iconv_in, &src, &src_s, &dst, &dst_s);
|
||||||
iconv_close(iconv_in);
|
iconv_close(iconv_in);
|
||||||
if (ret == static_cast<size_t>(-1)) {
|
if (ret == static_cast<size_t>(-1)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return strcmp(photoString, "PHOTO - 02/01/17 08:42:44");
|
return strcmp(photoHeader_string, "PHOTO - 02/01/17 08:42:44");
|
||||||
}
|
}
|
||||||
|
|
64
tests/WincvtTest.cpp
Normal file
64
tests/WincvtTest.cpp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* libragephoto RAGE Photo Parser
|
||||||
|
* Copyright (C) 2021 Syping
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* This software is provided as-is, no warranties are given to you, we are not
|
||||||
|
* responsible for anything with use of the software, you are self responsible.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <stringapiset.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char photoHeader[256] = {
|
||||||
|
0x50, 0x00, 0x48, 0x00, 0x4f, 0x00, 0x54, 0x00,
|
||||||
|
0x4f, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x20, 0x00,
|
||||||
|
0x30, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x30, 0x00,
|
||||||
|
0x31, 0x00, 0x2f, 0x00, 0x31, 0x00, 0x37, 0x00,
|
||||||
|
0x20, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3a, 0x00,
|
||||||
|
0x34, 0x00, 0x32, 0x00, 0x3a, 0x00, 0x34, 0x00,
|
||||||
|
0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
char photoHeader_string[256];
|
||||||
|
const int converted = WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast<wchar_t*>(photoHeader), -1, photoHeader_string, 256, NULL, NULL);
|
||||||
|
if (converted == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return strcmp(photoHeader_string, "PHOTO - 02/01/17 08:42:44");
|
||||||
|
}
|
Loading…
Reference in a new issue