text: ﻿//========= Copyright Valve Corporation, All rights reserved. ============//
  //
  //  LZMA Codec interface for engine.
  //
  //  LZMA SDK 9.38 beta
  //  2015-01-03 : Igor Pavlov : Public domain
  //  http://www.7-zip.org/
  //
  //========================================================================//
  
  #ifndef _LZMADECODER_H
  #define _LZMADECODER_H
  #pragma once
  
  // Thanks for the useful define namespacing, LZMA
  #include "../../thirdparty/lzma/C/7zVersion.h"
  #define LZMA_SDK_VERSION_MAJOR MY_VER_MAJOR
  #define LZMA_SDK_VERSION_MINOR MY_VER_MINOR
  
  #if !defined( _X360 )
  #define LZMA_ID				(('A'<<24)|('M'<<16)|('Z'<<8)|('L'))
  #else
  #define LZMA_ID				(('L'<<24)|('Z'<<16)|('M'<<8)|('A'))
  #endif
  
  // bind the buffer for correct identification
  #pragma pack(1)
  struct lzma_header_t
  {
  	unsigned int	id;
  	unsigned int	actualSize;		// always little endian
  	unsigned int	lzmaSize;		// always little endian
  	unsigned char	properties[5];
  };
  #pragma pack()
  
  class CLZMAStream;
  
  class CLZMA
  {
  public:
  	static unsigned int	Uncompress( unsigned char *pInput, unsigned char *pOutput );
  	static bool			IsCompressed( unsigned char *pInput );
  	static unsigned int	GetActualSize( unsigned char *pInput );
  };
  
  // For files besides the implementation, we forward declare a dummy struct. We can't unconditionally forward declare
  // this because LzmaEnc.h typedefs this directly to an unnamed struct :-/
  #ifndef CLzmaDec_t
  struct _CLzmaDec_t;
  #define CLzmaDec_t struct _CLzmaDec_t
  #endif
  
  class CLZMAStream
  {
  public:
  	CLZMAStream();
  	~CLZMAStream();
  
  	// Initialize a stream to read data from a LZMA style zip file, passing the original size from the zip headers.
  	// Streams with a source-engine style header (lzma_header_t) do not need an init call.
  	void InitZIPHeader( unsigned int nCompressedSize, unsigned int nOriginalSize );
  
  	// Attempt to read up to nMaxInputBytes from the compressed stream, writing up to nMaxOutputBytes to pOutput.
  	// Makes progress until blocked on input or output.
  	// Returns false if read stops due to an error or if called at EOF (GetExpectedBytesRemaining == 0)
  	bool Read( unsigned char *pInput, unsigned int nMaxInputBytes,
  	           unsigned char *pOutput, unsigned int nMaxOutputBytes,
  	           /* out */ unsigned int &nCompressedBytesRead, /* out */ unsigned int &nOutputBytesWritten );
  
  	// Get the expected uncompressed bytes yet to be read from this stream. Returns false if not yet known, such as
  	// before being fed the header.
  	bool GetExpectedBytesRemaining( /* out */ unsigned int &nBytesRemaining );
  
  private:
  	enum eHeaderParse
  	{
  		eHeaderParse_OK,
  		eHeaderParse_Fail,
  		eHeaderParse_NeedMoreBytes
  	};
  
  	eHeaderParse TryParseHeader( unsigned char *pInput, unsigned int nBytesAvailable, /* out */ unsigned int &nBytesConsumed );
  
  	void FreeDecoderState();
  	bool CreateDecoderState( const unsigned char *pProperties );
  
  	// Init from a zip-embedded LZMA stream. Requires the original size be passed from zip headers.
  	CLzmaDec_t *m_pDecoderState;
  
  	unsigned int m_nActualSize;
  	unsigned int m_nActualBytesRead;
  	unsigned int m_nCompressedSize;
  	unsigned int m_nCompressedBytesRead;
  
  	// If we have read past the header
  	bool m_bParsedHeader   : 1;
  	// If InitZIPHeader() was called. We're expecting a zip-style header and have size information.
  	bool m_bZIPStyleHeader : 1;
  };
  
  #endif
  