aboutsummaryrefslogtreecommitdiff
path: root/archived/network_compression.c
blob: eef9e3c15b07e491e6a5bf89425f89a4fe48cc64 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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;
}