Statistics
| Branch: | Revision:

grapes / som / ChunkIDSet / chunkids_encoding.c @ df7b954b

History | View | Annotate | Download (4.67 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
    uint8_t *meta_p;
39
    uint32_t type = h ? h->type : -1;
40
  
41
    int_cpy(buff + 4, type);
42
    int_cpy(buff + 8, meta_len);
43

    
44
    switch (type) {
45
        case CIST_BITMAP:
46
        {
47
            int elements;
48
            uint32_t c_min, c_max;
49
            c_min = c_max = h->n_elements ? h->elements[0] : 0;
50
            for (i = 1; i < h->n_elements; i++) {
51
                if (h->elements[i] < c_min)
52
                    c_min = h->elements[i];
53
                else if (h->elements[i] > c_max)
54
                    c_max = h->elements[i];
55
            }
56
            elements = h->n_elements ? c_max - c_min + 1 : 0;
57
            int_cpy(buff, elements);
58
            elements = elements / 8 + (elements % 8 ? 1 : 0);
59
            if (buff_len < elements + 16 + meta_len) {
60
                return -1;
61
            }
62
            int_cpy(buff + 12, c_min); //first value in the bitmap, i.e., base value
63
            memset(buff + 16, 0, elements);
64
            for (i = 0; i < h->n_elements; i++) {
65
                buff[16 + (h->elements[i] - c_min) / 8] |= 1 << ((h->elements[i] - c_min) % 8);
66
            }
67
            meta_p = buff + 16 + elements;
68
            break;
69
        }
70
        case CIST_PRIORITY:
71
            int_cpy(buff, h->n_elements);
72
            if (buff_len < h->n_elements * 4 + 12 + meta_len) {
73
                return -1;
74
            }
75
            for (i = 0; i < h->n_elements; i++) {
76
                int_cpy(buff + 12 + i * 4, h->elements[i]);
77
            }
78
            meta_p = buff + 12 + h->n_elements * 4;
79

    
80
            break;
81
        case -1:
82
            int_cpy(buff, 0);
83
            meta_p = buff + 12;
84
            break;
85
        default:
86
            fprintf(stderr, "Invalid ChunkID encoding type %d\n", type);
87

    
88
            return -1;
89
    }
90

    
91
    if (meta_len) {
92
        memcpy(meta_p, meta, meta_len);
93
    }
94

    
95
    return meta_p + meta_len - buff;
96
}
97

    
98
struct chunkID_set *decodeChunkSignaling(void **meta, int *meta_len, const uint8_t *buff, int buff_len)
99
{
100
    int i;
101
    uint32_t size;
102
    uint32_t type;
103
    struct chunkID_set *h;
104
    char cfg[32];
105
    const uint8_t *meta_p;
106

    
107
    size = int_rcpy(buff);
108
    type = int_rcpy(buff + 4);
109
    *meta_len = int_rcpy(buff + 8);
110

    
111
    if (type != -1) {
112
        sprintf(cfg, "size=%d,type=%d", size, type);
113
        h = chunkID_set_init(cfg);
114
        if (h == NULL) {
115
            fprintf(stderr, "Error in decoding chunkid set - not enough memory to create a chunkID set.\n");
116
            return NULL;
117
        }
118
    } else {
119
        h = NULL;
120
    }
121

    
122
    switch (type) {
123
        case CIST_BITMAP:
124
        {
125
            // uint8_t bitmap;
126
            int base;
127
            int byte_cnt;
128

    
129
            byte_cnt = size / 8 + (size % 8 ? 1 : 0);
130
            if (buff_len < 16 + byte_cnt + *meta_len) {
131
                fprintf(stderr, "Error in decoding chunkid set - wrong length\n");
132
                chunkID_set_free(h);
133
                return NULL;
134
            }
135
            base = int_rcpy(buff + 12);
136
            for (i = size - 1; i >= 0; i--) {
137
                if (buff[16 + (i / 8)] & 1 << (i % 8))
138
                    h->elements[h->n_elements++] = base + i;
139
            }
140
            meta_p = buff + 16 + byte_cnt;
141
            break;
142
        }
143
        case CIST_PRIORITY:
144
            if (buff_len != size * 4 + 12 + *meta_len) {
145
                fprintf(stderr, "Error in decoding chunkid set - wrong length.\n");
146
                chunkID_set_free(h);
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
            meta_p = buff + 12 + size * 4;
154
            break;
155
        case -1:
156
            meta_p = buff + 12;
157
            break;
158
        default:
159
            fprintf(stderr, "Error in decoding chunkid set - wrong val.\n");
160
            chunkID_set_free(h);
161
            return NULL; /* Not supported yet! */
162
    }
163

    
164
    if (*meta_len) {
165
        *meta = malloc(*meta_len);
166
        if (*meta != NULL) {
167
            memcpy(*meta, meta_p, *meta_len);
168
        } else {
169
            *meta_len = 0;
170
        }
171
    } else {
172
        *meta = NULL;
173
    }
174

    
175
    return h;
176
}