about summary refs log tree commit diff
path: root/src/engine/shared/compression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/shared/compression.cpp')
-rw-r--r--src/engine/shared/compression.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/engine/shared/compression.cpp b/src/engine/shared/compression.cpp
new file mode 100644
index 00000000..63e44699
--- /dev/null
+++ b/src/engine/shared/compression.cpp
@@ -0,0 +1,88 @@
+// copyright (c) 2007 magnus auvinen, see licence.txt for more info
+#include <base/system.h>
+
+#include "compression.h"
+
+// Format: ESDDDDDD EDDDDDDD EDD...  Extended, Data, Sign
+unsigned char *CVariableInt::Pack(unsigned char *pDst, int i) 
+{ 
+	*pDst = (i>>25)&0x40; // set sign bit if i<0
+	i = i^(i>>31); // if(i<0) i = ~i
+
+	*pDst |= i&0x3F; // pack 6bit into dst
+	i >>= 6; // discard 6 bits
+	if(i)
+	{
+		*pDst |= 0x80; // set extend bit
+		while(1)
+		{
+			pDst++;
+			*pDst = i&(0x7F); // pack 7bit
+			i >>= 7; // discard 7 bits
+			*pDst |= (i!=0)<<7; // set extend bit (may branch)
+			if(!i)
+				break;
+		}
+	}
+
+	pDst++;
+	return pDst; 
+} 
+ 
+const unsigned char *CVariableInt::Unpack(const unsigned char *pSrc, int *pInOut)
+{ 
+	int Sign = (*pSrc>>6)&1; 
+	*pInOut = *pSrc&0x3F; 
+
+	do
+	{ 
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7+7);
+
+		if(!(*pSrc&0x80)) break;
+		pSrc++;
+		*pInOut |= (*pSrc&(0x7F))<<(6+7+7+7);
+	} while(0);
+
+	pSrc++;
+	*pInOut ^= -Sign; // if(sign) *i = ~(*i)
+	return pSrc; 
+} 
+
+
+long CVariableInt::Decompress(const void *pSrc_, int Size, void *pDst_)
+{
+	const unsigned char *pSrc = (unsigned char *)pSrc_;
+	const unsigned char *pEnd = pSrc + Size;
+	int *pDst = (int *)pDst_;
+	while(pSrc < pEnd)
+	{
+		pSrc = CVariableInt::Unpack(pSrc, pDst);
+		pDst++;
+	}
+	return (long)((unsigned char *)pDst-(unsigned char *)pDst_);
+}
+
+long CVariableInt::Compress(const void *pSrc_, int Size, void *pDst_)
+{
+	int *pSrc = (int *)pSrc_;
+	unsigned char *pDst = (unsigned char *)pDst_;
+	Size /= 4;
+	while(Size)
+	{
+		pDst = CVariableInt::Pack(pDst, *pSrc);
+		Size--;
+		pSrc++;
+	}
+	return (long)(pDst-(unsigned char *)pDst_);
+}
+