summaryrefslogtreecommitdiff
path: root/src/pack.c
blob: 14c2e40f0f4ee9bdb3c9afd47b5dea1ccafb35ec (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
#include <stdio.h>

int frombigendian(const unsigned char in[4])
{
    return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
}

void tobigendian(const int in, unsigned char out[4])
{
    out[0] = (in >> 24) & 0xff;
    out[1] = (in >> 16) & 0xff;
    out[2] = (in >> 8) & 0xff;
    out[3] = in & 0xff;
}

/* function is lifted from */
/* https://github.com/heinrich5991/libtw2/blob/b9286674da94d3d45b9c10ffce517af394e2d58c/packer/src/lib.rs#L62 */
int readint(char **cp)
{
    int result = 0;
    int len = 1;

    unsigned char src = **cp;
    (*cp)++;

    int sign = ((src >> 6) & 1);
    result |= (src & 0b00111111);

    for (int i = 0; i < 4; i++)
    {
        // printf("(%d, ", src);
        if ((src & 0b10000000) == 0)
            break;

        src = **cp;
        (*cp)++;

        len++;

        if (i == 3 && (src & 0b11110000) != 0)
            printf("[ WARNING ] Non zero int padding!\n");

        result |= (src & 0b01111111) << (6 + 7 * i);
    }
    if (len > 1 && src == 0b00000000)
        printf("[ WARNING ] Overlong int encoding!\n");

    result ^= -sign;

    return result;
}

/* function is lifted from */
/* https://github.com/heinrich5991/libtw2/blob/b9286674da94d3d45b9c10ffce517af394e2d58c/packer/src/lib.rs#L105 */
void writeint(int i, char **cp)
{
    int sign = i < 0;
    unsigned int in = i;
    in = (in ^ -sign);
    char next = (in & 0b00111111);
    in >>= 6;

    char head = 0;
    if (in != 0)
        head |= 0b10000000;
    if (sign != 0)
        head |= 0b01000000;

    **cp = head | next;
    (*cp)++;

    while (in != 0)
    {
        next = (in & 0b01111111);
        in >>= 7;

        if (in != 0)
            head = 0b10000000;
        else
            head = 0;

        **cp = head | next;
        (*cp)++;
    }
}

/* function is copied from */
/* https://github.com/teeworlds/teeworlds/blob/a1911c8f7d8458fb4076ef8e7651e8ef5e91ab3e/src/game/gamecore.h#L68 */
void intstostr(const int *ints, int num, char *str)
{
    while (num)
    {
        str[0] = (((*ints) >> 24) & 0xff) - 128;
        str[1] = (((*ints) >> 16) & 0xff) - 128;
        str[2] = (((*ints) >> 8) & 0xff) - 128;
        str[3] = ((*ints) & 0xff) - 128;
        str += 4;
        ints++;
        num--;
    }
    str[-1] = 0;
}

void strtoint(const char *str, int num, int *ints)
{
    int intloc = 3;
    *ints = 0;
    while (num)
    {
        if (intloc < 0)
        {
            ints++;
            *ints = 0;
            intloc = 3;
        }
        *ints |= (*str + 128) << (8 * intloc);
        str++;
        intloc--;
        num--;
    }
}