summaryrefslogtreecommitdiff
path: root/utils/lzma/lzma.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/lzma/lzma.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/lzma/lzma.cpp')
-rw-r--r--utils/lzma/lzma.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/utils/lzma/lzma.cpp b/utils/lzma/lzma.cpp
new file mode 100644
index 0000000..164342b
--- /dev/null
+++ b/utils/lzma/lzma.cpp
@@ -0,0 +1,332 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// LZMA Codec interface for engine. Based largely on LzmaUtil.c in SDK
+//
+// LZMA SDK 9.38 beta
+// 2015-01-03 : Igor Pavlov : Public domain
+// http://www.7-zip.org/
+//
+//========================================================================//
+
+#ifdef POSIX
+#include <stdlib.h>
+#endif
+#include "tier0/memdbgon.h"
+#include "../../public/tier1/lzmaDecoder.h"
+#include "C/7zTypes.h"
+#include "C/LzmaEnc.h"
+#include "C/LzmaDec.h"
+#include "tier0/dbg.h"
+
+// Allocator to pass to LZMA functions
+static void *SzAlloc(void *p, size_t size) { return malloc(size); }
+static void SzFree(void *p, void *address) { free(address); }
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+// lzma buffers will have a 13 byte trivial header
+// [0] reserved
+// [1..4] dictionary size, little endian
+// [5..8] uncompressed size, little endian low word
+// [9..12] uncompressed size, little endian high word
+// [13..] lzma compressed data
+#define LZMA_ORIGINAL_HEADER_SIZE 13
+
+SRes CInStreamRam_StaticRead(void *p, void *buf, size_t *size );
+size_t COutStreamRam_StaticWrite(void *p, const void *buf, size_t size);
+
+class CInStreamRam : public ISeqInStream
+{
+ const Byte *Data;
+ size_t Size;
+ size_t Pos;
+
+public:
+ void Init(const Byte *data, size_t size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ Read = CInStreamRam_StaticRead;
+ }
+
+ SRes DoRead( void *buf, size_t *size )
+ {
+ size_t inSize = *size;
+ UInt32 remain = Size - Pos;
+ if (inSize > remain)
+ inSize = remain;
+
+ for (UInt32 i = 0; i < inSize; i++)
+ ((Byte *)buf)[i] = Data[Pos + i];
+
+ Pos += inSize;
+
+ *size = inSize;
+
+ return SZ_OK;
+ }
+};
+
+class COutStreamRam: public ISeqOutStream
+{
+ size_t Size;
+
+public:
+ Byte *Data;
+ size_t Pos;
+ bool Overflow;
+
+ void Init(Byte *data, size_t size)
+ {
+ Data = data;
+ Size = size;
+ Pos = 0;
+ Overflow = false;
+ Write = COutStreamRam_StaticWrite;
+ }
+
+ size_t DoWrite( const void *buf, size_t size )
+ {
+ UInt32 i;
+ for (i = 0; i < size && Pos < Size; i++)
+ Data[Pos++] = ((const Byte *)buf)[i];
+ if (i != size)
+ {
+ Overflow = true;
+ }
+ return i;
+ }
+};
+
+SRes CInStreamRam_StaticRead(void *p, void *buf, size_t *size )
+{
+ return reinterpret_cast<CInStreamRam *>(p)->DoRead( buf, size );
+}
+
+size_t COutStreamRam_StaticWrite(void *p, const void *buf, size_t size)
+{
+ return reinterpret_cast<COutStreamRam *>(p)->DoWrite( buf, size );
+}
+
+SRes
+LzmaEncode( const Byte *inBuffer,
+ size_t inSize,
+ Byte *outBuffer,
+ size_t outSize,
+ size_t *outSizeProcessed )
+{
+ // Based on Encode helper in SDK/LzmaUtil
+ *outSizeProcessed = 0;
+
+ const size_t kMinDestSize = LZMA_ORIGINAL_HEADER_SIZE;
+ if ( outSize < kMinDestSize )
+ {
+ return SZ_ERROR_FAIL;
+ }
+
+ CLzmaEncHandle enc;
+ SRes res;
+ CLzmaEncProps props;
+
+ enc = LzmaEnc_Create( &g_Alloc );
+ if ( !enc )
+ {
+ return SZ_ERROR_FAIL;
+ }
+
+ LzmaEncProps_Init( &props );
+ res = LzmaEnc_SetProps( enc, &props );
+
+ if ( res != SZ_OK )
+ {
+ return res;
+ }
+
+ COutStreamRam outStream;
+
+ outStream.Init( outBuffer, outSize );
+
+ Byte header[LZMA_PROPS_SIZE + 8];
+ size_t headerSize = LZMA_PROPS_SIZE;
+ int i;
+
+ res = LzmaEnc_WriteProperties( enc, header, &headerSize );
+ if ( res != SZ_OK )
+ {
+ return res;
+ }
+
+ // Uncompressed size after properties in header
+ for (i = 0; i < 8; i++)
+ {
+ header[headerSize++] = (Byte)(inSize >> (8 * i));
+ }
+
+ if ( outStream.DoWrite( header, headerSize ) != headerSize )
+ {
+ res = SZ_ERROR_WRITE;
+ }
+ else if ( res == SZ_OK )
+ {
+ CInStreamRam inStream;
+ inStream.Init( inBuffer, inSize );
+ res = LzmaEnc_Encode( enc, &outStream, &inStream, NULL, &g_Alloc, &g_Alloc );
+
+ if ( outStream.Overflow )
+ {
+ res = SZ_ERROR_FAIL;
+ }
+ else
+ {
+ *outSizeProcessed = outStream.Pos;
+ }
+ }
+
+ LzmaEnc_Destroy( enc, &g_Alloc, &g_Alloc );
+
+ return res;
+}
+
+//-----------------------------------------------------------------------------
+// Encoding glue. Returns non-null Compressed buffer if successful.
+// Caller must free.
+//-----------------------------------------------------------------------------
+unsigned char *LZMA_Compress( unsigned char *pInput,
+ unsigned int inputSize,
+ unsigned int *pOutputSize )
+{
+ *pOutputSize = 0;
+
+ // using same work buffer calcs as the SDK 105% + 64K
+ unsigned outSize = inputSize/20 * 21 + (1<<16);
+ unsigned char *pOutputBuffer = (unsigned char*)malloc( outSize );
+ if ( !pOutputBuffer )
+ {
+ return NULL;
+ }
+
+ // compress, skipping past our header
+ size_t compressedSize;
+ int result = LzmaEncode( pInput, inputSize, pOutputBuffer + sizeof( lzma_header_t ), outSize - sizeof( lzma_header_t ), &compressedSize );
+ if ( result != SZ_OK )
+ {
+ Warning( "LZMA encode failed (%i)\n", result );
+ Assert( result == SZ_OK );
+ free( pOutputBuffer );
+ return NULL;
+ }
+
+ // construct our header, strip theirs
+ lzma_header_t *pHeader = (lzma_header_t *)pOutputBuffer;
+ pHeader->id = LZMA_ID;
+ pHeader->actualSize = inputSize;
+ pHeader->lzmaSize = compressedSize - LZMA_ORIGINAL_HEADER_SIZE;
+ memcpy( pHeader->properties, pOutputBuffer + sizeof( lzma_header_t ), LZMA_PROPS_SIZE );
+
+ // shift the compressed data into place
+ memmove( pOutputBuffer + sizeof( lzma_header_t ),
+ pOutputBuffer + sizeof( lzma_header_t ) + LZMA_ORIGINAL_HEADER_SIZE,
+ compressedSize - LZMA_ORIGINAL_HEADER_SIZE );
+
+ // final output size is our header plus compressed bits
+ *pOutputSize = sizeof( lzma_header_t ) + compressedSize - LZMA_ORIGINAL_HEADER_SIZE;
+
+ return pOutputBuffer;
+}
+
+//-----------------------------------------------------------------------------
+// Above, but returns null if compression would not yield a size improvement
+//-----------------------------------------------------------------------------
+unsigned char *LZMA_OpportunisticCompress( unsigned char *pInput,
+ unsigned int inputSize,
+ unsigned int *pOutputSize )
+{
+ unsigned char *pRet = LZMA_Compress( pInput, inputSize, pOutputSize );
+ if ( *pOutputSize <= inputSize )
+ {
+ // compression got worse or stayed the same
+ free( pRet );
+ return NULL;
+ }
+
+ return pRet;
+}
+
+//-----------------------------------------------------------------------------
+// Decoding glue. Returns TRUE if succesful.
+//-----------------------------------------------------------------------------
+bool LZMA_Uncompress( unsigned char *pInBuffer,
+ unsigned char **ppOutBuffer,
+ unsigned int *pOutSize )
+{
+ *ppOutBuffer = NULL;
+ *pOutSize = 0;
+
+ lzma_header_t *pHeader = (lzma_header_t *)pInBuffer;
+ if ( pHeader->id != LZMA_ID )
+ {
+ // not ours
+ return false;
+ }
+
+ CLzmaDec state;
+
+ LzmaDec_Construct(&state);
+
+ if ( LzmaDec_Allocate(&state, pHeader->properties, LZMA_PROPS_SIZE, &g_Alloc) != SZ_OK )
+ {
+ return false;
+ }
+
+ unsigned char *pOutBuffer = (unsigned char *)malloc( pHeader->actualSize );
+ if ( !pOutBuffer )
+ {
+ LzmaDec_Free(&state, &g_Alloc);
+ return false;
+ }
+
+ // These are in/out variables
+ SizeT outProcessed = pHeader->actualSize;
+ SizeT inProcessed = pHeader->lzmaSize;
+ ELzmaStatus status;
+ SRes result = LzmaDecode( (Byte *)pOutBuffer, &outProcessed, (Byte *)(pInBuffer + sizeof( lzma_header_t ) ),
+ &inProcessed, (Byte *)pHeader->properties, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc );
+
+
+ LzmaDec_Free(&state, &g_Alloc);
+
+ if ( result != SZ_OK || pHeader->actualSize != outProcessed )
+ {
+ free( pOutBuffer );
+ return false;
+ }
+
+ *ppOutBuffer = pOutBuffer;
+ *pOutSize = pHeader->actualSize;
+
+ return true;
+}
+
+bool LZMA_IsCompressed( unsigned char *pInput )
+{
+ lzma_header_t *pHeader = (lzma_header_t *)pInput;
+ if ( pHeader && pHeader->id == LZMA_ID )
+ {
+ return true;
+ }
+
+ // unrecognized
+ return false;
+}
+
+unsigned int LZMA_GetActualSize( unsigned char *pInput )
+{
+ lzma_header_t *pHeader = (lzma_header_t *)pInput;
+ if ( pHeader && pHeader->id == LZMA_ID )
+ {
+ return pHeader->actualSize;
+ }
+
+ // unrecognized
+ return 0;
+}