1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 
3 #include "values.h"
4 #include "../bitfield.h"
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 
9 #define dec_uint16(b) (decode_raw16(*((raw_16 *) b)))
10 #define dec_raw24(b) (decode_raw24(*((raw_24 *) b)))
11 
12 static void enc_uint16(uint16_t u, char **buf);
13 static void enc_raw24(uint32_t u, char **buf);
14 
15 
decode_view_btree_value(const char *bytes, size_t len, view_btree_value_t **value)16 couchstore_error_t decode_view_btree_value(const char *bytes,
17                                            size_t len,
18                                            view_btree_value_t **value)
19 {
20     view_btree_value_t *v = NULL;
21     uint16_t  i, j;
22     uint32_t  sz;
23     const char    *bs;
24     size_t length;
25 
26     v = (view_btree_value_t *) malloc(sizeof(view_btree_value_t));
27     if (v == NULL) {
28         goto alloc_error;
29     }
30 
31     v->values = NULL;
32 
33     assert(len >= 2);
34     v->partition = dec_uint16(bytes);
35     bytes += 2;
36     len -= 2;
37 
38     bs = bytes;
39     length = len;
40 
41     v->num_values = 0;
42     while (len > 0) {
43 
44         assert(len >= 3);
45         sz = dec_raw24(bs);
46         bs += 3;
47         len -= 3;
48 
49         assert(len >= sz);
50         bs += sz;
51         len -= sz;
52         v->num_values++;
53     }
54 
55     if (len > 0) {
56         free_view_btree_value(v);
57         return COUCHSTORE_ERROR_CORRUPT;
58     }
59 
60     v->values = (sized_buf *) malloc(v->num_values * sizeof(sized_buf));
61 
62     if (v->values == NULL) {
63         goto alloc_error;
64     }
65 
66     for (j = 0; j< v->num_values; ++j) {
67         v->values[j].buf = NULL;
68     }
69 
70     i = 0;
71     len = length;
72     while (len > 0) {
73 
74         sz = dec_raw24(bytes);
75         bytes += 3;
76         len -= 3;
77 
78         v->values[i].size = sz;
79         v->values[i].buf = (char *) malloc(sz);
80 
81         if (v->values[i].buf == NULL) {
82             goto alloc_error;
83         }
84 
85         memcpy(v->values[i].buf, bytes, sz);
86         bytes += sz;
87         len -= sz;
88         i++;
89     }
90 
91     *value = v;
92 
93     return COUCHSTORE_SUCCESS;
94 
95  alloc_error:
96     free_view_btree_value(v);
97     return COUCHSTORE_ERROR_ALLOC_FAIL;
98 }
99 
100 
encode_view_btree_value(const view_btree_value_t *value, char **buffer, size_t *buffer_size)101 couchstore_error_t encode_view_btree_value(const view_btree_value_t *value,
102                                            char **buffer,
103                                            size_t *buffer_size)
104 {
105     char *buf = NULL, *b = NULL;
106     uint16_t i;
107     size_t sz = 0;
108 
109     sz += 2;                 /* partition */
110     /* values */
111     for (i = 0; i < value->num_values; ++i) {
112         sz += 3;             /* json value length */
113         sz += value->values[i].size;
114     }
115 
116     b = buf = (char *) malloc(sz);
117     if (buf == NULL) {
118         goto alloc_error;
119     }
120 
121     enc_uint16(value->partition, &b);
122 
123     for (i = 0; i < value->num_values; ++i) {
124         enc_raw24(value->values[i].size, &b);
125 
126         memcpy(b, value->values[i].buf, value->values[i].size);
127         b += value->values[i].size;
128     }
129 
130     *buffer = buf;
131     *buffer_size = sz;
132 
133     return COUCHSTORE_SUCCESS;
134 
135  alloc_error:
136     free(buf);
137     *buffer = NULL;
138     *buffer_size = 0;
139     return COUCHSTORE_ERROR_ALLOC_FAIL;
140 }
141 
142 
free_view_btree_value(view_btree_value_t *value)143 void free_view_btree_value(view_btree_value_t *value)
144 {
145     int i;
146     if (value == NULL) {
147         return;
148     }
149 
150     if (value->values != NULL){
151         for (i = 0; i < value->num_values; ++i) {
152             free(value->values[i].buf);
153         }
154         free(value->values);
155     }
156 
157     free(value);
158 }
159 
160 
decode_view_id_btree_value(const char *bytes, size_t len, view_id_btree_value_t **value)161 couchstore_error_t decode_view_id_btree_value(const char *bytes,
162                                               size_t len,
163                                               view_id_btree_value_t **value)
164 {
165     view_id_btree_value_t *v = NULL;
166     uint16_t i, j, num_keys;
167     const char *bs;
168     size_t sz, length;
169 
170     v = (view_id_btree_value_t *) malloc(sizeof(view_id_btree_value_t));
171     if (v == NULL) {
172         goto alloc_error;
173     }
174 
175     v->view_keys_map = NULL;
176 
177     assert(len >= 2);
178     v->partition = dec_uint16(bytes);
179     bytes += 2;
180     len -= 2;
181 
182     bs = bytes;
183     length = len;
184 
185     v->num_view_keys_map = 0;
186     while (len > 0) {
187 
188         assert(len >= 1);
189         bs += 1; /* view_id */
190         len -= 1;
191 
192         assert(len >= 2);
193         num_keys = dec_uint16(bs);
194         bs +=2;
195         len -= 2;
196 
197         for (j = 0; j < num_keys; ++j) {
198 
199             assert(len >= 2);
200             sz = dec_uint16(bs);
201             bs += 2;
202             len -= 2;
203 
204             assert(len >= sz);
205             bs += sz;
206             len -= sz;
207         }
208 
209         v->num_view_keys_map++;
210     }
211 
212     if (len > 0) {
213         free_view_id_btree_value(v);
214         return COUCHSTORE_ERROR_CORRUPT;
215     }
216 
217     v->view_keys_map = (view_keys_mapping_t *) malloc(v->num_view_keys_map *
218                                                      sizeof(view_keys_mapping_t));
219 
220     if (v->view_keys_map == NULL) {
221         goto alloc_error;
222     }
223 
224     for (j = 0; j< v->num_view_keys_map; ++j) {
225         v->view_keys_map[j].json_keys = NULL;
226     }
227 
228     i = 0;
229     len = length;
230     while (len > 0) {
231 
232         v->view_keys_map[i].view_id = bytes[0];
233         bytes += 1;
234         len -= 1;
235 
236         num_keys = dec_uint16(bytes);
237         v->view_keys_map[i].num_keys = num_keys;
238         bytes += 2;
239         len -= 2;
240 
241         v->view_keys_map[i].json_keys = (sized_buf *) malloc (num_keys * sizeof(sized_buf));
242         if (v->view_keys_map[i].json_keys == NULL) {
243             goto alloc_error;
244         }
245 
246         for (j = 0; j< num_keys; ++j) {
247             v->view_keys_map[i].json_keys[j].buf = NULL;
248         }
249 
250         for ( j = 0; j < num_keys; ++j) {
251 
252             sz = dec_uint16(bytes);
253             bytes += 2;
254             len -= 2;
255 
256             v->view_keys_map[i].json_keys[j].size = sz;
257             v->view_keys_map[i].json_keys[j].buf = (char *) malloc(sz);
258 
259             if (v->view_keys_map[i].json_keys[j].buf == NULL) {
260                 goto alloc_error;
261             }
262 
263             memcpy(v->view_keys_map[i].json_keys[j].buf, bytes, sz);
264             bytes += sz;
265             len -= sz;
266         }
267 
268         i++;
269     }
270 
271     *value = v;
272 
273     return COUCHSTORE_SUCCESS;
274 
275  alloc_error:
276     free_view_id_btree_value(v);
277     return COUCHSTORE_ERROR_ALLOC_FAIL;
278 }
279 
280 
encode_view_id_btree_value(const view_id_btree_value_t *value, char **buffer, size_t *buffer_size)281 couchstore_error_t encode_view_id_btree_value(const view_id_btree_value_t *value,
282                                               char **buffer,
283                                               size_t *buffer_size)
284 {
285     char *buf = NULL, *b = NULL;
286     size_t sz = 0;
287     uint16_t i, j;
288 
289     sz += 2;                 /* partition */
290 
291     /* view_keys_mappings */
292 
293     for (i = 0; i < value->num_view_keys_map; ++i) {
294         sz += 1;            /*view_id */
295         sz += 2;
296         for (j = 0; j < value->view_keys_map[i].num_keys; ++j) {
297             sz += 2;        /* size_t */
298             sz += value->view_keys_map[i].json_keys[j].size;
299         }
300     }
301 
302     b = buf = (char *) malloc(sz);
303     if (buf == NULL) {
304         goto alloc_error;
305     }
306 
307     enc_uint16(value->partition, &b);
308 
309     for (i = 0; i < value->num_view_keys_map; ++i) {
310 
311         b[0] = value->view_keys_map[i].view_id;
312         b += 1;
313 
314         enc_uint16(value->view_keys_map[i].num_keys, &b);
315 
316         for (j = 0; j < value->view_keys_map[i].num_keys; ++j) {
317 
318             enc_uint16(value->view_keys_map[i].json_keys[j].size, &b);
319 
320             memcpy(b, value->view_keys_map[i].json_keys[j].buf,
321                     value->view_keys_map[i].json_keys[j].size);
322             b += value->view_keys_map[i].json_keys[j].size;
323 
324         }
325     }
326 
327     *buffer = buf;
328     *buffer_size = sz;
329 
330     return COUCHSTORE_SUCCESS;
331 
332  alloc_error:
333     free(buf);
334     *buffer = NULL;
335     *buffer_size = 0;
336     return COUCHSTORE_ERROR_ALLOC_FAIL;
337 }
338 
339 
free_view_id_btree_value(view_id_btree_value_t *value)340 void free_view_id_btree_value(view_id_btree_value_t *value)
341 {
342     int i;
343     int j;
344 
345     if (value == NULL) {
346         return;
347     }
348 
349     if (value->view_keys_map != NULL){
350         for (i = 0; i < value->num_view_keys_map; ++i) {
351             if (value->view_keys_map[i].json_keys != NULL) {
352                 for (j = 0; j <value->view_keys_map[i].num_keys; ++j) {
353                     free (value->view_keys_map[i].json_keys[j].buf);
354                 }
355 
356                 free(value->view_keys_map[i].json_keys);
357             }
358         }
359 
360         free(value->view_keys_map);
361     }
362 
363     free(value);
364 }
365 
enc_uint16(uint16_t u, char **buf)366 static void enc_uint16(uint16_t u, char **buf)
367 {
368     raw_16 v = encode_raw16(u);
369     memcpy(*buf, &v, 2);
370     *buf += 2;
371 }
372 
enc_raw24(uint32_t u, char **buf)373 static void enc_raw24(uint32_t u, char **buf)
374 {
375     raw_24 v;
376     encode_raw24(u, &v);
377     memcpy(*buf, &v, 3);
378     *buf += 3;
379 }
380