Files
Leviathan/Library/Internal/source/compress/XZip.cpp
T
2026-06-01 12:46:52 +02:00

113 lines
2.6 KiB
C++

#include "../../include/compress/XZip.h"
#include "../../include/toolkit/safe_function.h"
#include <cstring>
#include <cassert>
#include <zlib/zlib.h>
namespace XZip
{
const unsigned char tag_mark[5] = { 0x00, 0x51, 0x3f, 0x99, 0x1a };
#pragma pack(1)
struct XZipHeader_t
{
unsigned char tag[5];
unsigned int src_size;
unsigned int compress_size;
};
#pragma pack()
size_t GetBufferSize( size_t original_size )
{
return compressBound( original_size ) + sizeof( XZipHeader_t );
}
size_t GetOriginalSize( const void* source, size_t source_len )
{
if( IsCompressed( source, source_len ) == false )
{
return 0;
}
const XZipHeader_t* header = static_cast< const XZipHeader_t* >( source );
return header->src_size;
}
bool IsCompressed( const void *source, size_t source_len )
{
if( source == 0 || source_len < sizeof( XZipHeader_t ) )
{
return false;
}
const XZipHeader_t* header = static_cast< const XZipHeader_t* >( source );
if( ::memcmp( header->tag, tag_mark, sizeof( tag_mark ) ) == 0 )
{
return true;
}
return false;
}
size_t Compress( const void* source, size_t source_len, void* buffer, size_t buffer_size, int ratio )
{
if( source == 0 || buffer == 0 || buffer_size <= sizeof( XZipHeader_t ) )
{
return 0;
}
XZipHeader_t* header = static_cast< XZipHeader_t* >( buffer );
s_memcpy( header->tag, sizeof( header->tag ), tag_mark, sizeof( header->tag ) );
header->src_size = source_len;
uLongf compress_size = buffer_size - sizeof( XZipHeader_t );
Bytef* compress_buffer = reinterpret_cast< Bytef* >( (static_cast< char* >( buffer ) + sizeof( XZipHeader_t )) );
if( compress2( compress_buffer, &compress_size, static_cast< const Bytef* >( source ), source_len, ratio ) != Z_OK )
{
return 0;
}
header->compress_size = compress_size;
return header->compress_size + sizeof( XZipHeader_t );
}
bool Uncompress( const void* source, size_t source_len, void* buffer, size_t buffer_size )
{
if( source == 0 || source_len <= sizeof( XZipHeader_t ) || buffer == 0 )
{
return false;
}
if( IsCompressed( source, source_len ) == false )
{
return false;
}
size_t org_size = GetOriginalSize( source, source_len );
if( buffer_size < org_size )
{
return false;
}
uLongf uncompress_size = buffer_size;
const Bytef* uncompress_buffer = reinterpret_cast< const Bytef* >( (static_cast< const char* >( source ) + sizeof( XZipHeader_t )) );
if( uncompress( static_cast< Bytef* >( buffer ), &uncompress_size, uncompress_buffer, source_len - sizeof( XZipHeader_t ) ) != Z_OK )
{
return false;
}
assert( uncompress_size == org_size );
return true;
}
}