Index: ext/libicpf/libicpf.vcproj
===================================================================
diff -u -re17c80d36eaa0430313e7d1058aa7a301d1510af -r6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f
--- ext/libicpf/libicpf.vcproj	(.../libicpf.vcproj)	(revision e17c80d36eaa0430313e7d1058aa7a301d1510af)
+++ ext/libicpf/libicpf.vcproj	(.../libicpf.vcproj)	(revision 6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f)
@@ -1,239 +1,245 @@
-<?xml version="1.0" encoding="windows-1250"?>
-<VisualStudioProject
-	ProjectType="Visual C++"
-	Version="7.10"
-	Name="libicpf"
-	ProjectGUID="{5510B933-046F-4F75-8B46-5E8279C8CCDE}"
-	Keyword="Win32Proj">
-	<Platforms>
-		<Platform
-			Name="Win32"/>
-	</Platforms>
-	<Configurations>
-		<Configuration
-			Name="Debug|Win32"
-			OutputDirectory="Debug"
-			IntermediateDirectory="Debug"
-			ConfigurationType="2"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBICPF_EXPORTS"
-				MinimalRebuild="TRUE"
-				BasicRuntimeChecks="3"
-				RuntimeLibrary="1"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="4"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/libicpf.dll"
-				LinkIncremental="2"
-				GenerateDebugInformation="TRUE"
-				ProgramDatabaseFile="$(OutDir)/libicpf.pdb"
-				SubSystem="2"
-				ImportLibrary="$(OutDir)/libicpf.lib"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-		<Configuration
-			Name="Release|Win32"
-			OutputDirectory="Release"
-			IntermediateDirectory="Release"
-			ConfigurationType="2"
-			CharacterSet="2">
-			<Tool
-				Name="VCCLCompilerTool"
-				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBICPF_EXPORTS"
-				RuntimeLibrary="0"
-				UsePrecompiledHeader="0"
-				WarningLevel="3"
-				Detect64BitPortabilityProblems="TRUE"
-				DebugInformationFormat="3"/>
-			<Tool
-				Name="VCCustomBuildTool"/>
-			<Tool
-				Name="VCLinkerTool"
-				OutputFile="$(OutDir)/libicpf.dll"
-				LinkIncremental="1"
-				GenerateDebugInformation="TRUE"
-				SubSystem="2"
-				OptimizeReferences="2"
-				EnableCOMDATFolding="2"
-				ImportLibrary="$(OutDir)/libicpf.lib"
-				TargetMachine="1"/>
-			<Tool
-				Name="VCMIDLTool"/>
-			<Tool
-				Name="VCPostBuildEventTool"/>
-			<Tool
-				Name="VCPreBuildEventTool"/>
-			<Tool
-				Name="VCPreLinkEventTool"/>
-			<Tool
-				Name="VCResourceCompilerTool"/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"/>
-			<Tool
-				Name="VCWebDeploymentTool"/>
-			<Tool
-				Name="VCManagedWrapperGeneratorTool"/>
-			<Tool
-				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
-		</Configuration>
-	</Configurations>
-	<References>
-	</References>
-	<Files>
-		<Filter
-			Name="Source Files"
-			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
-			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
-			<File
-				RelativePath=".\src\callback.cpp">
-			</File>
-			<File
-				RelativePath=".\src\cfg.cpp">
-			</File>
-			<File
-				RelativePath=".\src\conv.cpp">
-			</File>
-			<File
-				RelativePath=".\src\crc32.cpp">
-			</File>
-			<File
-				RelativePath=".\src\crypt.cpp">
-			</File>
-			<File
-				RelativePath=".\src\dumpctx.cpp">
-			</File>
-			<File
-				RelativePath=".\src\exception.cpp">
-			</File>
-			<File
-				RelativePath=".\src\file.cpp">
-			</File>
-			<File
-				RelativePath=".\src\libicpf.cpp">
-			</File>
-			<File
-				RelativePath=".\src\log.cpp">
-			</File>
-			<File
-				RelativePath=".\src\module.cpp">
-			</File>
-			<File
-				RelativePath=".\src\rijndael-alg-fst.c">
-			</File>
-			<File
-				RelativePath=".\src\rijndael-api-fst.c">
-			</File>
-			<File
-				RelativePath=".\src\sha256.c">
-			</File>
-			<File
-				RelativePath=".\src\str.cpp">
-			</File>
-			<File
-				RelativePath=".\src\str_help.cpp">
-			</File>
-		</Filter>
-		<Filter
-			Name="Header Files"
-			Filter="h;hpp;hxx;hm;inl;inc;xsd"
-			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
-			<File
-				RelativePath=".\src\callback.h">
-			</File>
-			<File
-				RelativePath=".\src\cfg.h">
-			</File>
-			<File
-				RelativePath=".\src\conv.h">
-			</File>
-			<File
-				RelativePath=".\src\crc32.h">
-			</File>
-			<File
-				RelativePath=".\src\crypt.h">
-			</File>
-			<File
-				RelativePath=".\src\dumpctx.h">
-			</File>
-			<File
-				RelativePath=".\src\err_codes.h">
-			</File>
-			<File
-				RelativePath=".\src\exception.h">
-			</File>
-			<File
-				RelativePath=".\src\file.h">
-			</File>
-			<File
-				RelativePath=".\src\gen_types.h">
-			</File>
-			<File
-				RelativePath=".\src\libicpf.h">
-			</File>
-			<File
-				RelativePath=".\src\log.h">
-			</File>
-			<File
-				RelativePath=".\src\macros.h">
-			</File>
-			<File
-				RelativePath=".\src\module.h">
-			</File>
-			<File
-				RelativePath=".\src\mutex.h">
-			</File>
-			<File
-				RelativePath=".\src\rijndael-alg-fst.h">
-			</File>
-			<File
-				RelativePath=".\src\rijndael-api-fst.h">
-			</File>
-			<File
-				RelativePath=".\src\sha256.h">
-			</File>
-			<File
-				RelativePath=".\src\str.h">
-			</File>
-			<File
-				RelativePath=".\src\str_help.h">
-			</File>
-		</Filter>
-		<Filter
-			Name="Resource Files"
-			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
-			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
-		</Filter>
-	</Files>
-	<Globals>
-	</Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="windows-1250"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="7.10"
+	Name="libicpf"
+	ProjectGUID="{5510B933-046F-4F75-8B46-5E8279C8CCDE}"
+	Keyword="Win32Proj">
+	<Platforms>
+		<Platform
+			Name="Win32"/>
+	</Platforms>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="Debug"
+			IntermediateDirectory="Debug"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBICPF_EXPORTS"
+				MinimalRebuild="TRUE"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="4"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/libicpf.dll"
+				LinkIncremental="2"
+				GenerateDebugInformation="TRUE"
+				ProgramDatabaseFile="$(OutDir)/libicpf.pdb"
+				SubSystem="2"
+				ImportLibrary="$(OutDir)/libicpf.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="Release"
+			IntermediateDirectory="Release"
+			ConfigurationType="2"
+			CharacterSet="2">
+			<Tool
+				Name="VCCLCompilerTool"
+				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBICPF_EXPORTS"
+				RuntimeLibrary="0"
+				UsePrecompiledHeader="0"
+				WarningLevel="3"
+				Detect64BitPortabilityProblems="TRUE"
+				DebugInformationFormat="3"/>
+			<Tool
+				Name="VCCustomBuildTool"/>
+			<Tool
+				Name="VCLinkerTool"
+				OutputFile="$(OutDir)/libicpf.dll"
+				LinkIncremental="1"
+				GenerateDebugInformation="TRUE"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				ImportLibrary="$(OutDir)/libicpf.lib"
+				TargetMachine="1"/>
+			<Tool
+				Name="VCMIDLTool"/>
+			<Tool
+				Name="VCPostBuildEventTool"/>
+			<Tool
+				Name="VCPreBuildEventTool"/>
+			<Tool
+				Name="VCPreLinkEventTool"/>
+			<Tool
+				Name="VCResourceCompilerTool"/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"/>
+			<Tool
+				Name="VCWebDeploymentTool"/>
+			<Tool
+				Name="VCManagedWrapperGeneratorTool"/>
+			<Tool
+				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Source Files"
+			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+			<File
+				RelativePath=".\src\callback.cpp">
+			</File>
+			<File
+				RelativePath=".\src\cfg.cpp">
+			</File>
+			<File
+				RelativePath=".\src\circ_buffer.cpp">
+			</File>
+			<File
+				RelativePath=".\src\conv.cpp">
+			</File>
+			<File
+				RelativePath=".\src\crc32.cpp">
+			</File>
+			<File
+				RelativePath=".\src\crypt.cpp">
+			</File>
+			<File
+				RelativePath=".\src\dumpctx.cpp">
+			</File>
+			<File
+				RelativePath=".\src\exception.cpp">
+			</File>
+			<File
+				RelativePath=".\src\file.cpp">
+			</File>
+			<File
+				RelativePath=".\src\libicpf.cpp">
+			</File>
+			<File
+				RelativePath=".\src\log.cpp">
+			</File>
+			<File
+				RelativePath=".\src\module.cpp">
+			</File>
+			<File
+				RelativePath=".\src\rijndael-alg-fst.c">
+			</File>
+			<File
+				RelativePath=".\src\rijndael-api-fst.c">
+			</File>
+			<File
+				RelativePath=".\src\sha256.c">
+			</File>
+			<File
+				RelativePath=".\src\str.cpp">
+			</File>
+			<File
+				RelativePath=".\src\str_help.cpp">
+			</File>
+		</Filter>
+		<Filter
+			Name="Header Files"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+			<File
+				RelativePath=".\src\callback.h">
+			</File>
+			<File
+				RelativePath=".\src\cfg.h">
+			</File>
+			<File
+				RelativePath=".\src\circ_buffer.h">
+			</File>
+			<File
+				RelativePath=".\src\conv.h">
+			</File>
+			<File
+				RelativePath=".\src\crc32.h">
+			</File>
+			<File
+				RelativePath=".\src\crypt.h">
+			</File>
+			<File
+				RelativePath=".\src\dumpctx.h">
+			</File>
+			<File
+				RelativePath=".\src\err_codes.h">
+			</File>
+			<File
+				RelativePath=".\src\exception.h">
+			</File>
+			<File
+				RelativePath=".\src\file.h">
+			</File>
+			<File
+				RelativePath=".\src\gen_types.h">
+			</File>
+			<File
+				RelativePath=".\src\libicpf.h">
+			</File>
+			<File
+				RelativePath=".\src\log.h">
+			</File>
+			<File
+				RelativePath=".\src\macros.h">
+			</File>
+			<File
+				RelativePath=".\src\module.h">
+			</File>
+			<File
+				RelativePath=".\src\mutex.h">
+			</File>
+			<File
+				RelativePath=".\src\rijndael-alg-fst.h">
+			</File>
+			<File
+				RelativePath=".\src\rijndael-api-fst.h">
+			</File>
+			<File
+				RelativePath=".\src\sha256.h">
+			</File>
+			<File
+				RelativePath=".\src\str.h">
+			</File>
+			<File
+				RelativePath=".\src\str_help.h">
+			</File>
+		</Filter>
+		<Filter
+			Name="Resource Files"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Index: ext/libicpf/src/circ_buffer.cpp
===================================================================
diff -u
--- ext/libicpf/src/circ_buffer.cpp	(revision 0)
+++ ext/libicpf/src/circ_buffer.cpp	(revision 6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f)
@@ -0,0 +1,496 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by J�zef Starosczyk                                *
+ *   ixen2@o2.pl                                                           *
+ *                                                                         *
+ *   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 2 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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include "circ_buffer.h"
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+BEGIN_ICPF_NAMESPACE
+
+// amount of bytes by which the buffer size will be incremented
+// if there is one byte to be put in a full buffer
+#define _BUFFER_INC			(size_t)512ULL
+
+// if there is at least _BUFFER_DEC free space in the buffer then the buffer
+// will be shrank (shrinked?)
+#define _BUFFER_DEC			(size_t)4096ULL
+
+// specifies if circular buffer should shrink the buffer size if there is too much free
+// space in the buffer
+#define _USE_SHRINKING		1
+
+// if defined to 1 then function ForwardSeek will empty the whole
+// internal buffer if it does not find the specified value inside of it
+#define _FAILSEEK_TRUNCATES		1
+
+circular_buffer::circular_buffer()
+{
+	m_pbyBuffer=NULL;
+	m_tSize=0;
+	m_tDataSize=0;
+	m_tBitsAtEndCount=0;
+}
+
+circular_buffer::circular_buffer(const circular_buffer& rSrc)
+{
+	copy_from(rSrc);
+}
+
+circular_buffer::~circular_buffer()
+{
+	destroy();
+}
+
+circular_buffer& circular_buffer::operator=(const circular_buffer& rSrc)
+{
+	// delete the old stuff
+	destroy();
+	copy_from(rSrc);
+	
+	return *this;
+}
+	
+void circular_buffer::copy_from(const circular_buffer& rSrc)
+{
+	if (rSrc.m_pbyBuffer && rSrc.m_tSize > 0)
+	{
+		// copy the old stuff
+		m_pbyBuffer=new byte_t[rSrc.m_tSize];
+		memcpy(m_pbyBuffer, rSrc.m_pbyBuffer, rSrc.m_tDataSize);
+		m_tSize=rSrc.m_tSize;
+		m_tDataSize=rSrc.m_tDataSize;
+	}
+	else
+	{
+		m_pbyBuffer=NULL;
+		m_tSize=0;
+		m_tDataSize=0;
+	}
+}
+
+void circular_buffer::destroy()
+{
+	delete [] m_pbyBuffer;
+	m_pbyBuffer=NULL;
+	m_tSize=0;
+	m_tDataSize=0;
+}
+
+void circular_buffer::push_data(const byte_t* pbyBuffer, size_t tCount)
+{
+	// check if there is enough space
+	if (m_tDataSize+tCount > m_tSize)
+		resize_buffer(m_tDataSize+tCount);
+	
+	// now there is enough space - fill it
+	memcpy(m_pbyBuffer+m_tDataSize, pbyBuffer, tCount);
+	
+	// increase the counters
+	m_tDataSize+=tCount;
+}
+
+void circular_buffer::push_data(circular_buffer& rcb)
+{
+	if (rcb.m_pbyBuffer && rcb.m_tDataSize)
+		push_data(rcb.m_pbyBuffer, rcb.m_tDataSize);
+}
+
+// pushes length and a string
+void circular_buffer::push_string(const char_t* pszString)
+{
+	if (pszString)
+	{
+		ulong_t ulLen=(ulong_t)(strlen(pszString)+1);
+		push_ulong(ulLen);
+		push_data((const uchar_t*)pszString, ulLen);
+	}
+	else
+	{
+		push_ulong(0);
+	}
+}
+
+void circular_buffer::push_ulonglong(ull_t ull)
+{
+	push_data((uchar_t*)&ull, sizeof(ull_t));
+}
+
+// pushes an unsigned long value
+void circular_buffer::push_ulong(ulong_t ulData)
+{
+	push_data((uchar_t*)&ulData, sizeof(ulong_t));
+}
+
+void circular_buffer::push_ushort(ushort_t wData)
+{
+	push_data((uchar_t*)&wData, sizeof(ushort_t));
+}
+
+void circular_buffer::push_uchar(uchar_t byData)
+{
+	push_data(&byData, 1);
+}
+
+size_t circular_buffer::pop_data(byte_t* pbyBuffer, size_t tCount)
+{
+	if (m_pbyBuffer == NULL || m_tDataSize == 0)
+		return 0;
+	
+	// how much data we are going to spare
+	size_t tRealCount=tCount;
+	if (m_tDataSize < tRealCount)
+		tRealCount=m_tDataSize;
+	
+	// copy the data
+	memcpy(pbyBuffer, m_pbyBuffer, tRealCount);
+	
+	// now move the data to beginning
+	skip_bytes(tRealCount);
+#if _USE_SHRINKING == 1
+	shrink_buffer();
+#endif
+	return tRealCount;
+}
+
+bool circular_buffer::pop_ulonglong(ull_t* pull)
+{
+	return (pop_data((byte_t*)pull, sizeof(ull_t)) == sizeof(ull_t));
+}
+
+bool circular_buffer::pop_ulong(ulong_t* pul)
+{
+	return (pop_data((byte_t*)pul, sizeof(ulong_t)) == sizeof(ulong_t));
+}
+
+bool circular_buffer::pop_ushort(ushort_t* pw)
+{
+	return (pop_data((byte_t*)pw, sizeof(ushort_t)) == sizeof(ushort_t));
+}
+	
+bool circular_buffer::pop_uchar(uchar_t* pby)
+{
+	return (pop_data((byte_t*)pby, 1) == 1);
+}
+
+long circular_buffer::pop_string(char_t** pszString)
+{
+	ulong_t ul;
+	if (!pop_ulong(&ul))
+	{
+		*pszString=NULL;
+		return -1;
+	}
+	
+	if (ul == 0)
+	{
+		*pszString = NULL;
+		return 0;
+	}
+	else
+	{
+		// check if there is enough data
+		if (m_tDataSize < ul)
+			return -1;
+		
+		// alloc buffer for a string
+		(*pszString)=new char_t[ul];
+		if (pop_data((byte_t*)(*pszString), ul) != ul)
+		{
+			delete [] (*pszString);
+			*pszString=NULL;
+			return -1;
+		}
+		else
+		{
+			(*pszString)[ul-1]='\0';		// just in case
+			return ul-1;					// without the '\0'
+		}
+	}
+}
+
+size_t circular_buffer::find(size_t tStartAt, ulong_t ulFnd)
+{
+//	printf("searching for %lu from %lu\n", ulFnd, ulStartAt);
+//	printf("internal structures: buf: 0x%lx, data size: %lu, buf size: %lu\n", m_pbyBuffer, m_tDataSize, m_tSize);
+	for (size_t i=tStartAt;i<m_tDataSize-3;i++)
+	{
+		if (((ulong_t*)(m_pbyBuffer+i))[0] == ulFnd)
+		{
+//			printf("found at %lu\n", i);
+			return i;
+		}
+	}
+	
+	return (size_t)-1;	
+}
+
+// returns 0 if there is no value (but a part of it may exist), 1 if found, -1 if not found
+int circular_buffer::forward_seek(ulong_t ulFnd)
+{
+	if (m_tDataSize < sizeof(ulong_t))
+		return FS_PARTIAL;		// cannot tell if there is such a value (may be a part of it)
+	
+	for (size_t i=0;i<m_tDataSize-3;i++)
+	{
+		if (((ulong_t*)(m_pbyBuffer+i))[0] == ulFnd)
+		{
+			// set this value at the beginning
+			skip_bytes(i);
+#if _USE_SHRINKING == 1
+			shrink_buffer();
+#endif
+			return FS_FOUND;
+		}
+	}
+
+#if _FAILSEEK_TRUNCATES == 1
+	// throw off almost the entire buffer (leave only the 3 bytes because they may contain 3/4th of ulFnd)
+	flush(sizeof(ulong_t)-1);
+#if _USE_SHRINKING == 1
+	shrink_buffer();
+#endif
+#endif
+	return FS_NOTFOUND;
+}
+
+void circular_buffer::skip_bytes(size_t tCount)
+{
+	if (tCount > m_tDataSize)
+		m_tDataSize=0;
+	else
+	{
+		memmove(m_pbyBuffer, m_pbyBuffer+tCount, m_tDataSize-tCount);
+		m_tDataSize-=tCount;
+	}
+}
+
+void circular_buffer::resize_buffer(size_t tNewSize)
+{
+	// modify the new length & alloc the new buffer
+	tNewSize=(tNewSize & ~(_BUFFER_INC-1)) + _BUFFER_INC;
+	if (tNewSize < m_tSize)
+		return;
+	
+	byte_t *pszBuf=new byte_t[tNewSize];
+	
+	if (m_pbyBuffer && m_tDataSize > 0)
+	{
+		// copy the old buffer to the new one
+		memcpy(pszBuf, m_pbyBuffer, m_tDataSize);
+		
+		// destroy the old buffer
+		delete [] m_pbyBuffer;
+	}
+	
+	// update data
+	m_pbyBuffer=pszBuf;
+	m_tSize=tNewSize;
+}
+
+void circular_buffer::shrink_buffer()
+{
+#if _USE_SHRINKING == 1
+	// check the current size of the data
+	size_t tNewSize=(m_tDataSize & ~(_BUFFER_INC-1)) + _BUFFER_INC;
+	if (m_tSize-tNewSize > _BUFFER_DEC)
+	{
+		// we must shrink the buffer
+		byte_t *pszBuf=new byte_t[tNewSize];
+		memcpy(pszBuf, m_pbyBuffer, m_tDataSize);
+		delete [] m_pbyBuffer;
+		
+		m_pbyBuffer=pszBuf;
+		m_tSize=tNewSize;
+	}
+#endif
+}
+
+void circular_buffer::flush(size_t tToLeave)
+{
+	if (m_tDataSize > tToLeave)
+		skip_bytes(m_tDataSize-tToLeave);
+}
+
+void circular_buffer::push_bits(ulong_t ulBits, byte_t byCount)
+{
+	assert(byCount <= 32 && byCount >= 1);	// count of bits must be a sane value
+	assert(m_tBitsAtEndCount <= 7);			// the internal bits count must be from the range [0..7]. For 8 bits in a buffer 
+											// there is value of 0.
+	
+	do
+	{
+		// check if we have to add the bits to the last byte of a buffer
+		if (m_tBitsAtEndCount != 0)
+		{
+			// count of bits to copy into the last byte of the internal buffer
+			ulong_t ulCopy=(ulong_t)((byCount < 8-m_tBitsAtEndCount) ? byCount : 8-m_tBitsAtEndCount);
+			
+			// make some space for the incoming data
+			m_pbyBuffer[m_tDataSize-1] >>= ulCopy;
+			
+			// get the full byte from the in
+			byte_t uc=(byte_t)(ulBits & 0x000000ff);
+			
+			// we are getting from it only ulCopy lowest bits, so shift if a bit
+			uc <<= 8-ulCopy;
+			
+			// and apply
+			m_pbyBuffer[m_tDataSize-1] |= uc;
+			
+			// a bit of corrections
+			ulBits >>= ulCopy;
+			byCount-=(byte_t)ulCopy;
+			m_tBitsAtEndCount+=ulCopy;
+			if (m_tBitsAtEndCount == 8)
+				m_tBitsAtEndCount = 0;
+		}
+		else
+		{
+			// now there is something to add at the beginning of a next byte
+			// if there are some full bytes to add then simply add it through the
+			// PushData.
+			if (byCount >= 8)
+			{
+				// push the whole 8 bits as a byte into the buffer. Operation safe only
+				// on the little endian machines.
+				ulong_t ulCount=byCount/8;
+				push_data(((const byte_t*)&ulBits), ulCount);
+				
+				// corrections
+				ulBits >>= ulCount*8;
+				byCount-=(byte_t)(ulCount*8);
+			}
+			else
+			{
+				// we are about to add <8 bits of data into the last byte of a buffer which does not exist yet
+				// get the full byte from the input ulong
+				byte_t uc=(byte_t)(ulBits & 0x000000ff);
+			
+				// shift it a bit
+				uc <<= 8-byCount;
+				
+				// and add as a next byte
+				push_data(&uc, 1);
+				
+//				Dump();
+				
+				// corrections
+				m_tBitsAtEndCount = byCount;
+				ulBits = 0;			// since there are no data left
+				byCount = 0;	// no data left
+			}
+		}
+	}
+	while(byCount > 0);
+}
+
+// finished the operation of pushing bits, so we could use normal Push/PopData
+/*void circular_buffer::PushBitsFinish()
+{
+	// check if there is unfinished byte at the end
+	if (m_tBitsAtEndCount != 0)
+	{
+		m_pbyBuffer[m_tDataSize-1] >>= 8-m_tBitsAtEndCount;
+		m_tBitsAtEndCount=0;
+	}
+}*/
+
+// enumerates all the bit-packs that exists in a buffer. If there were any bits operations performed
+// on a buffer - they must be finished by the PushBitsFinish.
+void circular_buffer::enum_bit_packets(ulong_t ulBitsCount, PFNBITSCALLBACK pfn, void* pParam)
+{
+	assert(ulBitsCount >= 1 && ulBitsCount <=8);
+	assert(pfn);
+	
+	ushort_t w=0;		// internal buffer for the next data from the class's buffer
+	ulong_t ulBits=0;	// count of bits that was left in w
+	
+	size_t tIndex=0;	// current index in the class's buffer
+	for (;;)
+	{
+		// make sure there is enough data in w so the next operation can succeed
+		// if there is less data in w than requested
+		if (ulBits < ulBitsCount)
+		{
+			// is there something left to read from the internal buffer
+			if (tIndex < m_tDataSize)
+			{
+				// append some bits into the buffer.
+				// NOTE: we are sure that there are at least 8 bits space in w
+				if (tIndex == m_tDataSize && m_tBitsAtEndCount != 0)
+				{
+					// there are less than 8 bits left. add only the part that exists
+					byte_t uc=(byte_t)(m_pbyBuffer[tIndex++] >> (8-m_tBitsAtEndCount));
+					w |= (ushort_t)(uc) << ulBits;
+				}
+				else
+				{
+					w |= (ushort_t)(m_pbyBuffer[tIndex++]) << ulBits;
+					ulBits+=8;
+				}
+			}
+			else
+			{
+				// are there any bits left in the w ?
+				if (ulBits > 0)
+				{
+					// there are some bits left, so we should add a bit or two to make sure nothing is lost
+//					printf("$$$ Some (%lu) bits left. Current cache=%u\n", ulBits, w);
+					ulBits=ulBitsCount;
+				}
+				else
+				{
+					// there are no data left in the internal buffer, so finish the operation
+//					printf("&&& Leaving with %lu bits left\n", ulBits);
+					return;
+				}
+			}
+		}
+		else
+		{
+			// call the callback function with the ucData as a param
+			byte_t uc=(byte_t)(w & 0xff) << (8-ulBitsCount);
+			uc >>= 8-ulBitsCount;
+			
+			(*pfn)(uc, pParam);
+			
+			// update variables
+			ulBits-=ulBitsCount;
+			w >>= ulBitsCount;
+		}
+	}
+}
+
+/*void circular_buffer::dump()
+{
+	printf("circular_buffer::Dump()\n\tsize of data: %lu\n\tsizeof the buffer: %lu\n\tbits at end: %lu", m_tDataSize, m_tSize, m_tBitsAtEndCount);
+	for (unsigned long i=0;i<m_tDataSize;i++)
+	{
+		if ( (i % 16) == 0 )
+			printf("\n\t");
+		
+		printf("0x%02lx,", (unsigned long)m_pbyBuffer[i]);
+	}
+	printf("\n");
+}
+*/
+
+END_ICPF_NAMESPACE
Index: ext/libicpf/src/circ_buffer.h
===================================================================
diff -u
--- ext/libicpf/src/circ_buffer.h	(revision 0)
+++ ext/libicpf/src/circ_buffer.h	(revision 6595bc5b8ba8079e6651ecb5f4c99a7aedc5af9f)
@@ -0,0 +1,101 @@
+/***************************************************************************
+ *   Copyright (C) 2004 by J�zef Starosczyk                                *
+ *   ixen2@o2.pl                                                           *
+ *                                                                         *
+ *   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 2 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, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef __CIRCULARBUFFER_H__
+#define __CIRCULARBUFFER_H__
+
+#include "libicpf.h"
+#include "gen_types.h"
+
+BEGIN_ICPF_NAMESPACE
+
+// forward_seek() results
+#define FS_NOTFOUND		-1
+#define FS_PARTIAL		0
+#define FS_FOUND		1
+
+typedef void(*PFNBITSCALLBACK)(unsigned char uc, void* pParam);
+
+class LIBICPF_API circular_buffer
+{
+public:
+	// construction/destruction
+	circular_buffer();
+	circular_buffer(const circular_buffer& rSrc);
+	~circular_buffer();
+	
+	circular_buffer& operator=(const circular_buffer& rSrc);
+	
+	void destroy();		// destroys the contents of this class
+	
+	// operations
+	void push_data(const byte_t* pbyBuffer, size_t tCount);
+	void push_data(circular_buffer& rcb);
+	
+	void push_string(const char_t* pszString);		// pushes length and a string
+	void push_ulonglong(ull_t ull);
+	void push_ulong(ulong_t ulData);		// pushes an unsigned long value
+	void push_ushort(ushort_t wData);
+	void push_uchar(uchar_t byData);
+	
+	size_t pop_data(byte_t* pbyBuffer, size_t tCount);
+	bool pop_ulonglong(ull_t* pull);
+	bool pop_ulong(ulong_t* pul);
+	long pop_string(char_t** pszString);		// returns the length of alloc string (-1 for error)
+	bool pop_ushort(ushort_t* pw);
+	bool pop_uchar(uchar_t* pby);
+	
+	// operation on single bits
+	void push_bits(ulong_t ulBits, byte_t byCount);
+//	void PushBitsFinish();		// finishes the operation of pushing bits, so we could use normal Push/PopData
+	void enum_bit_packets(unsigned long ulBitsCount, PFNBITSCALLBACK pfn, void* pParam);
+	
+	// searching
+	int forward_seek(ulong_t ulFnd);			// seeks for the value and skips the bytes previous to it
+	size_t find(size_t tStartAt, ulong_t ulFnd);		// searches for the specified value in the buffer, returns an index
+													// (size_t)-1 if not found
+	
+	void skip_bytes(size_t tCount);	// skips some bytes from the beginning of a buffer
+	void flush(size_t ulToLeave);	// removes (almost) all the data from a buffer
+	void clear() { m_tDataSize=0; };
+	
+	size_t get_datasize() const { return m_tDataSize; };
+	bool is_empty() const { return m_tDataSize == 0; };
+	
+	operator byte_t*() const { return m_pbyBuffer; };
+	byte_t* get_buffer() const { return m_pbyBuffer; };
+	
+//	void dump();
+	
+protected:
+	void copy_from(const circular_buffer& rSrc);
+	void resize_buffer(size_t tNewSize);		// enlarges buffer
+	void shrink_buffer();
+	
+public:
+	byte_t *m_pbyBuffer;			// internal buffer
+	size_t m_tSize;					// size of the buffer
+	size_t m_tDataSize;				// data size inside the buffer (the last byte could be partially filled with data
+									// so when using PopData instead of PopBitsX make sure you understand it).
+	size_t m_tBitsAtEndCount;		// count of bits in the last byte of the buffer. 0 if the last byte is full of data
+};
+
+END_ICPF_NAMESPACE
+
+#endif