summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_intbuf.x
blob: b68396eaadd69214be4a010cbcb7a8444f6ee4e3 (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
static inline Eina_Intbuf *eina_intbuf_new(void)
{
   Eina_Intbuf *buf;

   buf = calloc(1, sizeof (Eina_Intbuf));
   return buf;
}

static void eina_intbuf_free(Eina_Intbuf *buf)
{
   free(buf->bytes);
   free(buf);
}

static inline void eina_intbuf_push(Eina_Intbuf *buf, int data)
{
   int delta = data - buf->last_data;
   unsigned char *tmp;
   unsigned char data[5];
   unsigned char idx = 4;
   Eina_Bool neg = EINA_FALSE;

   /* detect negative value */
   if (delta < 0)
     {
        delta *= -1;
        neg = EINA_TRUE;
     }

   /* Special case for storing negative value and no continuation bit */
   data[idx] = (delta & 0x3F) | (neg ? 0x40 : 0x0);

   /* Update index and delta after storing data */
   delta = delta >> 6;
   idx--;

   while (delta)
     {
        /* Normal case where we store the data with the continuing bit */
        data[idx] = (delta & 0x7F) | 0x80;

        /* Update index and delta after storing data */
        delta = delta >> 7;
        idx--;
     }

   /* resize bytes buffer and store data at the end of the buffer */
   tmp = realloc(buf->bytes, buf->length + 5 - idx);
   if (!tmp) return ;

   buf->bytes = tmp;
   memcpy(tmp, data + idx + 1, 5 - idx);

   /* update last data to the last pushed data */
   buf->last_data = data;
}

static inline inline Eina_Bool eina_intbuf_read(Eina_Intbuf *buf,
                                                unsigned int *buffer_offset,
                                                int *data)
{
   int delta = 0;

   /* end of the buffer ! */
   if (*buffer_offset >= buf->length)
     return EINA_FALSE;

   /* as long as we find the continuation bit */
   while (buf->bytes[*buffer_offset] & 0x80)
     {
        /* we can add those bit to the current delta value */
        delta = (delta << 7) + (buf->bytes[*buffer_offset] & 0x7F);
        (*buffer_offset)++;
     }

   /* handling the specific case of negative value and end of integer stream */
   delta = (delta << 7) + (buf->bytes[*buffer_offset] & 0x3F);
   if (buf->bytes[*buffer_offset] & 0x40)
     delta *= -1;

   /* update data by delta value */
   *data += delta;
   return EINA_TRUE;
}