Statistics
| Branch: | Revision:

grapes / som / ChunkIDSet / chunkids_encoding.c @ 43271130

History | View | Annotate | Download (4.82 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *
4
 *  This is free software; see lgpl-2.1.txt
5
 */
6

    
7
#include <arpa/inet.h>
8
#include <stdlib.h>
9
#include <string.h>
10
#include <stdio.h>
11
#include <stdint.h>
12

    
13
#include "chunkids_private.h"
14
#include "chunkidset.h"
15
#include "trade_sig_la.h"
16

    
17
static inline void int_cpy(uint8_t *p, int v)
18
{
19
  int tmp;
20
  
21
  tmp = htonl(v);
22
  memcpy(p, &tmp, 4);
23
}
24

    
25
static inline int int_rcpy(const uint8_t *p)
26
{
27
  int tmp;
28
  
29
  memcpy(&tmp, p, 4);
30
  tmp = ntohl(tmp);
31

    
32
  return tmp;
33
}
34

    
35
int encodeChunkSignaling(const struct chunkID_set *h, const void *meta, int meta_len, uint8_t *buff, int buff_len)
36
{
37
    int i;
38
    uint32_t type_length;
39
    int_cpy(buff + 4, 0);
40
    int_cpy(buff + 8, meta_len);
41
    switch (h->type) {
42
        case CIST_BITMAP:
43
        {
44
            int elements;
45
            uint32_t c_min, c_max;
46
            c_min = c_max = h->n_elements ? h->elements[0] : 0;
47
            for (i = 1; i < h->n_elements; i++) {
48
                if (h->elements[i] < c_min)
49
                    c_min = h->elements[i];
50
                else if (h->elements[i] > c_max)
51
                    c_max = h->elements[i];
52
            }
53
            elements = c_max - c_min + 1;
54
            type_length = elements | (h->type << ((sizeof (h->n_elements) - 1)*8));
55
            int_cpy(buff, type_length);
56
            elements = elements / 8 + (elements % 8 ? 1 : 0);
57
            if (buff_len < (elements * 4) + 16 + meta_len) {
58
                return -1;
59
            }
60
            int_cpy(buff + 12, c_min); //first value in the bitmap, i.e., base value
61
            for (i = 0; i < h->n_elements; i++) {
62
                buff[16 + (h->elements[i] - c_min) / 8] |= 1 << ((h->elements[i] - c_min) % 8);
63
            }
64
            if (meta_len) {
65
                memcpy(buff + 16 + elements * 4, meta, meta_len);
66
            }
67
            return 16 + elements * 4 + meta_len;
68
        }
69
        case CIST_PRIORITY:
70
        default:
71
        {
72
            type_length = h->n_elements | (h->type << ((sizeof (h->n_elements) - 1)*8));
73
            int_cpy(buff, type_length);
74
            if (buff_len < h->n_elements * 4 + 12 + meta_len) {
75
                return -1;
76
            }
77
            for (i = 0; i < h->n_elements; i++) {
78
                int_cpy(buff + 12 + i * 4, h->elements[i]);
79
            }
80
            if (meta_len) {
81
                memcpy(buff + h->n_elements * 4 + 12, meta, meta_len);
82
            }
83
            return h->n_elements * 4 + 12 + meta_len;
84
        }
85
    }
86
}
87

    
88
struct chunkID_set *decodeChunkSignaling(void **meta, int *meta_len, const uint8_t *buff, int buff_len)
89
{
90
    int i, val;
91
    uint32_t size;
92
    uint8_t type;
93
    struct chunkID_set *h;
94
    char cfg[32];
95
    size = int_rcpy(buff);
96
    type = size >> (sizeof (size) - 1)*8;
97
    size = (size << 8) >> 8;
98
    val = int_rcpy(buff + 4);
99
    *meta_len = int_rcpy(buff + 8);
100
    sprintf(cfg, "size=%d", size);
101
    sprintf(cfg, "%s,type=%d", cfg, type);
102
    h = chunkID_set_init(cfg);
103

    
104
    if (h == NULL) {
105
        fprintf(stderr, "Error in decoding chunkid set - not enough memory to create a chunkID set.\n");
106
        return NULL;
107
    }
108
    if (val) {
109
        return h; /* Not supported yet! */
110
    }
111
    switch (h->type) {
112
        case CIST_BITMAP:
113
        {
114
            // uint8_t bitmap;
115
            int base;
116
            int byte_cnt;
117
            byte_cnt = size / 8 + (size % 8 ? 1 : 0);
118
            if (buff_len < 16 + byte_cnt + *meta_len) {
119
                return NULL;
120
            }
121
            base = int_rcpy(buff + 12);
122
            for (i = 0; i < size; i++) {
123
                if (buff[16 + (i / 8)] & 1 << (i % 8))
124
                    h->elements[h->n_elements++] = base + i;
125
            }
126
            if (!realloc(h->elements, h->n_elements * sizeof (int))) {
127
                fprintf(stderr, "Error in decoding chunkid set while realloc.\n");
128
                return NULL;
129
            }
130
            h->size = h->n_elements;
131
            if (*meta_len) {
132
                *meta = malloc(*meta_len);
133
                if (*meta != NULL) {
134
                    memcpy(*meta, buff + 16 + byte_cnt, *meta_len);
135
                } else {
136
                    *meta_len = 0;
137
                }
138
            } else {
139
                *meta = NULL;
140
            }
141
            break;
142
        }
143
        case CIST_PRIORITY:
144
        default:
145
        {
146
            if (buff_len != size * 4 + 12 + *meta_len) {
147
                return NULL;
148
            }
149
            for (i = 0; i < size; i++) {
150
                h->elements[i] = int_rcpy(buff + 12 + i * 4);
151
            }
152
            h->n_elements = size;
153
            if (*meta_len) {
154
                *meta = malloc(*meta_len);
155
                if (*meta != NULL) {
156
                    memcpy(*meta, buff + 12 + size * 4, *meta_len);
157
                } else {
158
                    *meta_len = 0;
159
                }
160
            } else {
161
                *meta = NULL;
162
            }
163
            break;
164
        }
165
    }
166
    return h;
167
}