aboutsummaryrefslogtreecommitdiff
path: root/source/archived/network_compression.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/archived/network_compression.c')
-rw-r--r--source/archived/network_compression.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/source/archived/network_compression.c b/source/archived/network_compression.c
new file mode 100644
index 0000000..eef9e3c
--- /dev/null
+++ b/source/archived/network_compression.c
@@ -0,0 +1,154 @@
+#include <strings.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64;
+
+size_t
+GetMaximumCompressedOutputSize(size_t FileSize)
+{
+ // TODO: figure out equation
+ return FileSize*2 + 256;
+}
+
+u32
+RLECompress(size_t InSize, u8* In, size_t MaxOutSize, u8* OutBase)
+{
+ u8* Out = OutBase;
+
+#define MAX_LITERAL_COUNT 255
+#define MAX_RUN_COUNT 255
+ u32 LiteralCount = 0;
+ u8 Literals[MAX_LITERAL_COUNT] = {0};
+
+ u8 *InEnd = In + InSize;
+ while(In < InEnd)
+ {
+ u8 StartingValue = In[0];
+ size_t Run = 1; // first one is the character itself
+ while((Run < (InEnd - In)) &&
+ (Run < MAX_RUN_COUNT) &&
+ (In[Run] == StartingValue))
+ {
+ ++Run;
+ }
+
+ if ((Run > 1) ||
+ (LiteralCount == MAX_LITERAL_COUNT)) // stop doing runs when there is no
+ // space left in the buffer.
+ {
+ // Encode a literal/run pair
+ u8 LiteralCount8 = (u8)LiteralCount;
+ assert(LiteralCount8 == LiteralCount);
+ *Out++ = LiteralCount8;
+
+ for(u32 LiteralIndex = 0;
+ LiteralIndex < LiteralCount;
+ ++LiteralIndex)
+ {
+ *Out++ = Literals[LiteralIndex];
+ }
+ LiteralCount = 0;
+
+ u8 Run8 = (u8)Run;
+ assert(Run8 == Run);
+ *Out++ = Run8;
+
+ *Out++ = StartingValue;
+
+ In += Run;
+ }
+ else
+ {
+ // Buffer literals, you have to because we are encoding them in pairs
+ Literals[LiteralCount++] = StartingValue;
+ ++In;
+ }
+
+ }
+#undef MAX_LITERAL_COUNT
+#undef MAX_RUN_COUNT
+
+ assert(In == InEnd);
+
+ size_t OutSize = Out - OutBase;
+ assert(OutSize <= MaxOutSize);
+
+ return OutSize;
+}
+
+void
+RLEDecompress(size_t InSize, u8* In, size_t OutSize, u8* Out)
+{
+ u8 *InEnd = In + InSize;
+ while(In < InEnd)
+ {
+ // TODO: I think Casey made a mistake and this should be an u8
+ u8 LiteralCount = *In++;
+ while(LiteralCount--)
+ {
+ *Out++ = *In++;
+ }
+
+ // Alternate to Run
+ u8 RepCount = *In++;
+ u8 RepValue = *In++;
+ while(RepCount--)
+ {
+ *Out++ = RepValue;
+ }
+ }
+
+ assert(In == InEnd);
+}
+
+int main(int Argc, char* Argv[]) {
+
+ if (Argc < 2)
+ {
+ fprintf(stderr, "Usage: %s [compress|decompress]\n", Argv[0]);
+ return 1;
+ }
+
+ char* Command = Argv[1];
+
+ if (!strcmp(Command, "compress"))
+ {
+ u32* Message = (u32*)L"abcabcbbbbbbb";
+ size_t MessageSize = wcslen((const wchar_t*)Message) * 4;
+
+ size_t OutBufferSize = GetMaximumCompressedOutputSize(MessageSize);
+ u8 OutBuffer[OutBufferSize + 8];
+ bzero(OutBuffer, OutBufferSize + 8);
+ *(u32*)OutBuffer = MessageSize;
+
+ size_t CompressedSize = RLECompress(MessageSize, (u8*)Message, OutBufferSize, OutBuffer + 8);
+
+ s32 OutFile = open("test.compressed", O_WRONLY | O_CREAT, 0600);
+
+ write(OutFile, OutBuffer, CompressedSize);
+
+ fprintf(stdout, "%lu -> %lu bytes\n", MessageSize, CompressedSize);
+ }
+ else if (!strcmp(Command, "decompress"))
+ {
+ fprintf(stderr, "Not implemented yet.\n");
+ }
+ else
+ fprintf(stderr, "Unknown command: '%s'\n", Command);
+
+ return 0;
+}