mirror of
https://github.com/aaru-dps/libaaruformat.git
synced 2025-12-16 19:24:40 +00:00
Refactor image info structure to use fixed-size arrays and improve UTF-16 to UTF-8 conversion
This commit is contained in:
@@ -156,10 +156,20 @@ include(3rdparty/flac.cmake)
|
|||||||
include(3rdparty/lzma.cmake)
|
include(3rdparty/lzma.cmake)
|
||||||
include(3rdparty/xxhash.cmake)
|
include(3rdparty/xxhash.cmake)
|
||||||
include(3rdparty/blake3.cmake)
|
include(3rdparty/blake3.cmake)
|
||||||
|
|
||||||
|
# Find and link ICU library for UTF-16LE to UTF-8 conversion
|
||||||
|
find_package(ICU COMPONENTS uc REQUIRED)
|
||||||
|
|
||||||
if(TARGET blake3)
|
if(TARGET blake3)
|
||||||
target_link_libraries(aaruformat blake3)
|
target_link_libraries(aaruformat blake3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Add ICU include directories and link library to the target
|
||||||
|
if(ICU_FOUND)
|
||||||
|
target_include_directories(aaruformat PRIVATE ${ICU_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(aaruformat ${ICU_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
macro(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target)
|
macro(TARGET_LINK_LIBRARIES_WHOLE_ARCHIVE target)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
foreach(lib IN LISTS ARGN)
|
foreach(lib IN LISTS ARGN)
|
||||||
|
|||||||
@@ -807,18 +807,18 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
typedef struct ImageInfo // NOLINT
|
typedef struct ImageInfo // NOLINT
|
||||||
{
|
{
|
||||||
uint8_t HasPartitions; ///< Image contains partitions (or tracks for optical media)
|
uint8_t HasPartitions; ///< Image contains partitions (or tracks for optical media)
|
||||||
uint8_t HasSessions; ///< Image contains sessions (optical media only)
|
uint8_t HasSessions; ///< Image contains sessions (optical media only)
|
||||||
uint64_t ImageSize; ///< Size of the image without headers
|
uint64_t ImageSize; ///< Size of the image without headers
|
||||||
uint64_t Sectors; ///< Sectors contained in the image
|
uint64_t Sectors; ///< Sectors contained in the image
|
||||||
uint32_t SectorSize; ///< Size of sectors contained in the image
|
uint32_t SectorSize; ///< Size of sectors contained in the image
|
||||||
uint8_t *Version; ///< Image version
|
char Version[32]; ///< Image version
|
||||||
uint8_t *Application; ///< Application that created the image
|
char Application[64]; ///< Application that created the image
|
||||||
uint8_t *ApplicationVersion; ///< Version of the application that created the image
|
char ApplicationVersion[32]; ///< Version of the application that created the image
|
||||||
int64_t CreationTime; ///< Image creation time
|
int64_t CreationTime; ///< Image creation time
|
||||||
int64_t LastModificationTime; ///< Image last modification time
|
int64_t LastModificationTime; ///< Image last modification time
|
||||||
uint32_t MediaType; ///< Media type represented by the image
|
uint32_t MediaType; ///< Media type represented by the image
|
||||||
uint8_t XmlMediaType; ///< Type of the media represented by the image to use in XML sidecars
|
uint8_t XmlMediaType; ///< Type of the media represented by the image to use in XML sidecars
|
||||||
} ImageInfo;
|
} ImageInfo;
|
||||||
|
|
||||||
/** \addtogroup SectorTags Per-sector metadata tag types
|
/** \addtogroup SectorTags Per-sector metadata tag types
|
||||||
|
|||||||
90
src/create.c
90
src/create.c
@@ -22,6 +22,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <unicode/ucnv.h>
|
||||||
|
#include <unicode/ustring.h>
|
||||||
|
|
||||||
#include "aaruformat.h"
|
#include "aaruformat.h"
|
||||||
#include "enums.h"
|
#include "enums.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -73,17 +76,7 @@ static void cleanup_failed_create(aaruformatContext *ctx)
|
|||||||
ctx->readableSectorTags = NULL;
|
ctx->readableSectorTags = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx->imageInfo.ApplicationVersion != NULL)
|
// ApplicationVersion and Version are fixed-size arrays, not pointers - no need to free
|
||||||
{
|
|
||||||
free(ctx->imageInfo.ApplicationVersion);
|
|
||||||
ctx->imageInfo.ApplicationVersion = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx->imageInfo.Version != NULL)
|
|
||||||
{
|
|
||||||
free(ctx->imageInfo.Version);
|
|
||||||
ctx->imageInfo.Version = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx->imageStream != NULL)
|
if(ctx->imageStream != NULL)
|
||||||
{
|
{
|
||||||
@@ -368,20 +361,75 @@ void *aaruf_create(const char *filepath, const uint32_t media_type, const uint32
|
|||||||
|
|
||||||
// Initialize image info
|
// Initialize image info
|
||||||
TRACE("Initializing image info");
|
TRACE("Initializing image info");
|
||||||
ctx->imageInfo.Application = ctx->header.application;
|
|
||||||
ctx->imageInfo.ApplicationVersion = (uint8_t *)malloc(32);
|
// Convert application name from UTF-16LE to UTF-8 using libicu
|
||||||
if(ctx->imageInfo.ApplicationVersion != NULL)
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
int32_t app_name_utf16_len = AARU_HEADER_APP_NAME_LEN / 2; // UTF-16LE uses 2 bytes per character
|
||||||
|
UChar *app_name_utf16 = (UChar *)malloc(app_name_utf16_len * sizeof(UChar));
|
||||||
|
|
||||||
|
if(app_name_utf16 != NULL)
|
||||||
{
|
{
|
||||||
memset(ctx->imageInfo.ApplicationVersion, 0, 32);
|
// Convert raw UTF-16LE bytes to UChar (UTF-16, host endian)
|
||||||
sprintf((char *)ctx->imageInfo.ApplicationVersion, "%d.%d", ctx->header.applicationMajorVersion,
|
for(int32_t j = 0; j < app_name_utf16_len; j++)
|
||||||
ctx->header.applicationMinorVersion);
|
{
|
||||||
|
app_name_utf16[j] = (UChar)(ctx->header.application[j * 2] | (ctx->header.application[j * 2 + 1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get required length for UTF-8
|
||||||
|
int32_t app_name_utf8_len = 0;
|
||||||
|
u_strToUTF8(NULL, 0, &app_name_utf8_len, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
|
||||||
|
if(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR)
|
||||||
|
{
|
||||||
|
status = U_ZERO_ERROR;
|
||||||
|
|
||||||
|
// Ensure it fits in the Application buffer (64 bytes including null terminator)
|
||||||
|
if(app_name_utf8_len < 64)
|
||||||
|
{
|
||||||
|
u_strToUTF8(ctx->imageInfo.Application, 64, NULL, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
|
||||||
|
if(U_FAILURE(status))
|
||||||
|
{
|
||||||
|
TRACE("Error converting application name to UTF-8: %d, using raw bytes", status);
|
||||||
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
memcpy(ctx->imageInfo.Application, ctx->header.application, AARU_HEADER_APP_NAME_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Application name too long for buffer, truncating");
|
||||||
|
u_strToUTF8(ctx->imageInfo.Application, 63, NULL, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
ctx->imageInfo.Application[63] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Error getting UTF-8 length: %d, using raw bytes", status);
|
||||||
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
memcpy(ctx->imageInfo.Application, ctx->header.application, AARU_HEADER_APP_NAME_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(app_name_utf16);
|
||||||
}
|
}
|
||||||
ctx->imageInfo.Version = (uint8_t *)malloc(32);
|
else
|
||||||
if(ctx->imageInfo.Version != NULL)
|
|
||||||
{
|
{
|
||||||
memset(ctx->imageInfo.Version, 0, 32);
|
TRACE("Could not allocate memory for UTF-16 conversion, using raw bytes");
|
||||||
sprintf((char *)ctx->imageInfo.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
memcpy(ctx->imageInfo.Application, ctx->header.application, AARU_HEADER_APP_NAME_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set application version string directly in the fixed-size array
|
||||||
|
memset(ctx->imageInfo.ApplicationVersion, 0, 32);
|
||||||
|
sprintf(ctx->imageInfo.ApplicationVersion, "%d.%d", ctx->header.applicationMajorVersion,
|
||||||
|
ctx->header.applicationMinorVersion);
|
||||||
|
|
||||||
|
// Set image version string directly in the fixed-size array
|
||||||
|
memset(ctx->imageInfo.Version, 0, 32);
|
||||||
|
sprintf(ctx->imageInfo.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
|
||||||
|
|
||||||
ctx->imageInfo.MediaType = ctx->header.mediaType;
|
ctx->imageInfo.MediaType = ctx->header.mediaType;
|
||||||
ctx->imageInfo.ImageSize = 0;
|
ctx->imageInfo.ImageSize = 0;
|
||||||
ctx->imageInfo.CreationTime = ctx->header.creationTime;
|
ctx->imageInfo.CreationTime = ctx->header.creationTime;
|
||||||
|
|||||||
86
src/open.c
86
src/open.c
@@ -22,6 +22,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <unicode/ucnv.h>
|
||||||
|
#include <unicode/ustring.h>
|
||||||
|
|
||||||
#include <aaruformat.h>
|
#include <aaruformat.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -41,12 +44,6 @@ static void cleanup_open_failure(aaruformatContext *ctx)
|
|||||||
free(ctx->readableSectorTags);
|
free(ctx->readableSectorTags);
|
||||||
ctx->readableSectorTags = NULL;
|
ctx->readableSectorTags = NULL;
|
||||||
|
|
||||||
free(ctx->imageInfo.ApplicationVersion);
|
|
||||||
ctx->imageInfo.ApplicationVersion = NULL;
|
|
||||||
|
|
||||||
free(ctx->imageInfo.Version);
|
|
||||||
ctx->imageInfo.Version = NULL;
|
|
||||||
|
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,20 +242,75 @@ void *aaruf_open(const char *filepath) // NOLINT(readability-function-size)
|
|||||||
memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
|
memset(ctx->readableSectorTags, 0, sizeof(bool) * MaxSectorTag);
|
||||||
|
|
||||||
TRACE("Setting up image info");
|
TRACE("Setting up image info");
|
||||||
ctx->imageInfo.Application = ctx->header.application;
|
|
||||||
ctx->imageInfo.ApplicationVersion = (uint8_t *)malloc(32);
|
// Convert application name from UTF-16LE to UTF-8 using libicu
|
||||||
if(ctx->imageInfo.ApplicationVersion != NULL)
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
|
int32_t app_name_utf16_len = AARU_HEADER_APP_NAME_LEN / 2; // UTF-16LE uses 2 bytes per character
|
||||||
|
UChar *app_name_utf16 = (UChar *)malloc(app_name_utf16_len * sizeof(UChar));
|
||||||
|
|
||||||
|
if(app_name_utf16 != NULL)
|
||||||
{
|
{
|
||||||
memset(ctx->imageInfo.ApplicationVersion, 0, 32);
|
// Convert raw UTF-16LE bytes to UChar (UTF-16, host endian)
|
||||||
sprintf((char *)ctx->imageInfo.ApplicationVersion, "%d.%d", ctx->header.applicationMajorVersion,
|
for(int32_t j = 0; j < app_name_utf16_len; j++)
|
||||||
ctx->header.applicationMinorVersion);
|
{
|
||||||
|
app_name_utf16[j] = (UChar)(ctx->header.application[j * 2] | (ctx->header.application[j * 2 + 1] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get required length for UTF-8
|
||||||
|
int32_t app_name_utf8_len = 0;
|
||||||
|
u_strToUTF8(NULL, 0, &app_name_utf8_len, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
|
||||||
|
if(U_SUCCESS(status) || status == U_BUFFER_OVERFLOW_ERROR)
|
||||||
|
{
|
||||||
|
status = U_ZERO_ERROR;
|
||||||
|
|
||||||
|
// Ensure it fits in the Application buffer (64 bytes including null terminator)
|
||||||
|
if(app_name_utf8_len < 64)
|
||||||
|
{
|
||||||
|
u_strToUTF8(ctx->imageInfo.Application, 64, NULL, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
|
||||||
|
if(U_FAILURE(status))
|
||||||
|
{
|
||||||
|
TRACE("Error converting application name to UTF-8: %d, using raw bytes", status);
|
||||||
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
strncpy(ctx->imageInfo.Application, (const char *)ctx->header.application, 63);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Application name too long for buffer, truncating");
|
||||||
|
u_strToUTF8(ctx->imageInfo.Application, 63, NULL, app_name_utf16, app_name_utf16_len, &status);
|
||||||
|
ctx->imageInfo.Application[63] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("Error getting UTF-8 length: %d, using raw bytes", status);
|
||||||
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
strncpy(ctx->imageInfo.Application, (const char *)ctx->header.application, 63);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(app_name_utf16);
|
||||||
}
|
}
|
||||||
ctx->imageInfo.Version = (uint8_t *)malloc(32);
|
else
|
||||||
if(ctx->imageInfo.Version != NULL)
|
|
||||||
{
|
{
|
||||||
memset(ctx->imageInfo.Version, 0, 32);
|
TRACE("Could not allocate memory for UTF-16 conversion, using raw bytes");
|
||||||
sprintf((char *)ctx->imageInfo.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
|
// Fallback: just copy what we can
|
||||||
|
memset(ctx->imageInfo.Application, 0, 64);
|
||||||
|
strncpy(ctx->imageInfo.Application, (const char *)ctx->header.application, 63);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set application version string directly in the fixed-size array
|
||||||
|
memset(ctx->imageInfo.ApplicationVersion, 0, 32);
|
||||||
|
sprintf(ctx->imageInfo.ApplicationVersion, "%d.%d", ctx->header.applicationMajorVersion,
|
||||||
|
ctx->header.applicationMinorVersion);
|
||||||
|
|
||||||
|
// Set image version string directly in the fixed-size array
|
||||||
|
memset(ctx->imageInfo.Version, 0, 32);
|
||||||
|
sprintf(ctx->imageInfo.Version, "%d.%d", ctx->header.imageMajorVersion, ctx->header.imageMinorVersion);
|
||||||
|
|
||||||
ctx->imageInfo.MediaType = ctx->header.mediaType;
|
ctx->imageInfo.MediaType = ctx->header.mediaType;
|
||||||
|
|
||||||
// Read the index header
|
// Read the index header
|
||||||
@@ -474,4 +526,4 @@ void *aaruf_open(const char *filepath) // NOLINT(readability-function-size)
|
|||||||
|
|
||||||
TRACE("Exiting aaruf_open() = %p", ctx);
|
TRACE("Exiting aaruf_open() = %p", ctx);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user