about summary refs log tree commit diff
path: root/src/engine/e_compression.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/e_compression.c')
-rw-r--r--src/engine/e_compression.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/engine/e_compression.c b/src/engine/e_compression.c
new file mode 100644
index 00000000..fa7d7866
--- /dev/null
+++ b/src/engine/e_compression.c
@@ -0,0 +1,147 @@
+/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+#include "e_system.h"
+#include <string.h>
+
+/* Format: ESDDDDDD EDDDDDDD EDD...  Extended, Data, Sign */
+unsigned char *vint_pack(unsigned char *dst, int i) 
+{ 
+	*dst = (i>>25)&0x40; /* set sign bit if i<0 */
+	i = i^(i>>31); /* if(i<0) i = ~i */
+
+	*dst |= i&0x3F; /* pack 6bit into dst */
+	i >>= 6; /* discard 6 bits */
+	if(i)
+	{
+		*dst |= 0x80; /* set extend bit */
+		while(1)
+		{
+			dst++;
+			*dst = i&(0x7F); /* pack 7bit */
+			i >>= 7; /* discard 7 bits */
+			*dst |= (i!=0)<<7; /* set extend bit (may branch) */
+			if(!i)
+				break;
+		}
+	}
+
+	dst++;
+	return dst; 
+} 
+ 
+const unsigned char *vint_unpack(const unsigned char *src, int *i)
+{ 
+	int sign = (*src>>6)&1; 
+	*i = *src&0x3F; 
+
+	do
+	{ 
+		if(!(*src&0x80)) break;
+		src++;
+		*i |= (*src&(0x7F))<<(6);
+
+		if(!(*src&0x80)) break;
+		src++;
+		*i |= (*src&(0x7F))<<(6+7);
+
+		if(!(*src&0x80)) break;
+		src++;
+		*i |= (*src&(0x7F))<<(6+7+7);
+
+		if(!(*src&0x80)) break;
+		src++;
+		*i |= (*src&(0x7F))<<(6+7+7+7);
+	} while(0);
+
+	src++;
+	*i ^= -sign; /* if(sign) *i = ~(*i) */
+	return src; 
+} 
+
+
+long intpack_decompress(const void *src_, int size, void *dst_)
+{
+	const unsigned char *src = (unsigned char *)src_;
+	const unsigned char *end = src + size;
+	int *dst = (int *)dst_;
+	while(src < end)
+	{
+		src = vint_unpack(src, dst);
+		dst++;
+	}
+	return (long)((unsigned char *)dst-(unsigned char *)dst_);
+}
+
+long intpack_compress(const void *src_, int size, void *dst_)
+{
+	int *src = (int *)src_;
+	unsigned char *dst = (unsigned char *)dst_;
+	size /= 4;
+	while(size)
+	{
+		dst = vint_pack(dst, *src);
+		size--;
+		src++;
+	}
+	return (long)(dst-(unsigned char *)dst_);
+}
+
+
+/* */
+long zerobit_compress(const void *src_, int size, void *dst_)
+{
+	unsigned char *src = (unsigned char *)src_;
+	unsigned char *dst = (unsigned char *)dst_;
+	
+	while(size)
+	{
+		unsigned char bit = 0x80;
+		unsigned char mask = 0;
+		int dst_move = 1;
+		int chunk = size < 8 ? size : 8;
+		int b;
+		size -= chunk;
+		
+		for(b = 0; b < chunk; b++, bit>>=1)
+		{
+			if(*src)
+			{
+				dst[dst_move] = *src;
+				mask |= bit;
+				dst_move++;
+			}
+			
+			src++;
+		}
+		
+		*dst = mask;
+		dst += dst_move;
+	}
+	
+	return (long)(dst-(unsigned char *)dst_);
+}
+
+long zerobit_decompress(const void *src_, int size, void *dst_)
+{
+	unsigned char *src = (unsigned char *)src_;
+	unsigned char *dst = (unsigned char *)dst_;
+	unsigned char *end = src + size;
+
+	
+	while(src != end)
+	{
+		unsigned char bit = 0x80;
+		unsigned char mask = *src++;
+		int b;
+		
+		for(b = 0; b < 8; b++, bit>>=1)
+		{
+			if(mask&bit)
+				*dst++ = *src++;
+			else
+				*dst++ = 0;
+		}
+	}
+	
+	return (long)(dst-(unsigned char *)dst_);
+}
+