/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
//
//	plBSDiffBuffer - A utility class for writing and applying a difference
//					buffer--i.e. a buffer containing a series of modifications
//					that will modify an old data buffer to match a new one. 
//					It's a useful utility class when doing binary file
//				    patching, for example, as you can write out the changes
//				    to this class, get back a data buffer suitable for writing,
//					then use this class again later to reconstruct the new buffer.
//
//					This class is copied in structure (not substance) from
//					plDiffBuffer. It is based on bsdiff-4.1 from BSD
//                  Linux (http://www.daemonology.org/bsdiff). It's *extremely*
//					hard to read code (written by a PhD), but it works well. The
//					original BSD code has been modified to have the bzip2 pipes 
//					it used to compress data removed. It has also been converted
//					to work a C++ utility class.
//
//					There isn't really an Add or Copy command in bsdiff. It just
//					uses three control numbers and two diff/data buffers.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef _plBSDiffBuffer_h
#define _plBSDiffBuffer_h

#include "hsTypes.h"
#include "hsStream.h"

//// Class Definition ////////////////////////////////////////////////////////

class hsRAMStream;
class plBSDiffBuffer
{
	protected:

		hsBool			fWriting;
		UInt32			fNewLength, fPatchLength;
		unsigned char*	fPatchBuffer;

	public:

		plBSDiffBuffer( UInt32 newLength, UInt32 oldLength = 0 );		// Constructor for writing new buffers. oldLength isn't required but helpful for optimizations
		plBSDiffBuffer( void *buffer, UInt32 length );	// Constructor for applying a given diff set
														// to an old buffer
		virtual ~plBSDiffBuffer();


		/// Creation/write functions

		//	Diff() creates the diff buffer from the new and old. 
		UInt32	Diff( UInt32 oldLength, void *oldBuffer, UInt32 newLength, void *newBuffer );

		// GetBuffer() will copy the diff stream into a new buffer and return it. You are responsible for freeing the buffer.
		void	GetBuffer( UInt32 &length, void *&bufferPtr );


		/// Apply functions

		// Apply() is another way to call Patch().
		UInt32	Apply( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer )
		{ return Patch(oldLength, oldBuffer, newLength, newBuffer); };

		// Patch() will take this diff buffer and apply it to the given old buffer,
		// allocating and producing a new buffer. You are responsible for freeing the new buffer.
		UInt32	Patch( UInt32 oldLength, void *oldBuffer, UInt32 &newLength, void *&newBuffer );

	private:
		
		UInt32	IReadUnsignedInt8(unsigned char *buf);
		void	IWriteUnsignedInt8(UInt32 x,unsigned char *buf);
		void	ISafeMemcpy(unsigned char *dest, unsigned char *src, size_t nbytes,
							unsigned char *destend, unsigned char *srcend);
		void	ISplit(Int32 *I,Int32 *V,UInt32 start,UInt32 len,UInt32 h);
		void	IQSuffixSort(Int32 *I,Int32 *V,unsigned char *old,UInt32 oldsize);
		UInt32	IMatchLen( unsigned char *oldBuffer, UInt32 oldLength,
						   unsigned char *newBuffer, UInt32 newLength);
		UInt32	ISearch( Int32 *I,
					     unsigned char *oldBuffer, UInt32 oldLength,
						 unsigned char *newBuffer, UInt32 newLength,
						 UInt32 st, UInt32 en, Int32 *pos);


};

#endif // _plBSDiffBuffer_h