10
/* set to 0 for alloc debugging, e.g. through valgrind */
11
#define BENCODE_MIN_BUFFER_PIECE_LEN 512
13
#define BENCODE_HASH_BUCKETS 31 /* prime numbers work best */
15
struct __bencode_buffer_piece {
18
struct __bencode_buffer_piece *next;
21
struct __bencode_free_list {
24
struct __bencode_free_list *next;
26
struct __bencode_hash {
27
struct bencode_item *buckets[BENCODE_HASH_BUCKETS];
34
static bencode_item_t __bencode_end_marker = {
35
.type = BENCODE_END_MARKER,
36
.iov[0].iov_base = "e",
45
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end);
49
static void __bencode_item_init(bencode_item_t *item) {
50
item->last_child = item->parent = item->child = item->sibling = NULL;
53
static void __bencode_container_init(bencode_item_t *cont) {
54
cont->iov[0].iov_len = 1;
55
cont->iov[1].iov_base = "e";
56
cont->iov[1].iov_len = 1;
61
static void __bencode_dictionary_init(bencode_item_t *dict) {
62
dict->type = BENCODE_DICTIONARY;
63
dict->iov[0].iov_base = "d";
65
__bencode_container_init(dict);
68
static void __bencode_list_init(bencode_item_t *list) {
69
list->type = BENCODE_LIST;
70
list->iov[0].iov_base = "l";
71
__bencode_container_init(list);
74
static struct __bencode_buffer_piece *__bencode_piece_new(unsigned int size) {
75
struct __bencode_buffer_piece *ret;
77
if (size < BENCODE_MIN_BUFFER_PIECE_LEN)
78
size = BENCODE_MIN_BUFFER_PIECE_LEN;
79
ret = BENCODE_MALLOC(sizeof(*ret) + size);
90
int bencode_buffer_init(bencode_buffer_t *buf) {
91
buf->pieces = __bencode_piece_new(0);
94
buf->free_list = NULL;
99
static void *__bencode_alloc(bencode_buffer_t *buf, unsigned int size) {
100
struct __bencode_buffer_piece *piece;
110
if (size <= piece->left)
113
piece = __bencode_piece_new(size);
118
piece->next = buf->pieces;
121
assert(size <= piece->left);
130
void bencode_buffer_free(bencode_buffer_t *buf) {
131
struct __bencode_free_list *fl;
132
struct __bencode_buffer_piece *piece, *next;
134
for (fl = buf->free_list; fl; fl = fl->next)
137
for (piece = buf->pieces; piece; piece = next) {
143
static bencode_item_t *__bencode_item_alloc(bencode_buffer_t *buf, unsigned int payload) {
146
ret = __bencode_alloc(buf, sizeof(struct bencode_item) + payload);
150
__bencode_item_init(ret);
154
bencode_item_t *bencode_dictionary(bencode_buffer_t *buf) {
157
ret = __bencode_item_alloc(buf, 0);
160
__bencode_dictionary_init(ret);
164
bencode_item_t *bencode_list(bencode_buffer_t *buf) {
167
ret = __bencode_item_alloc(buf, 0);
170
__bencode_list_init(ret);
174
static void __bencode_container_add(bencode_item_t *parent, bencode_item_t *child) {
180
assert(child->parent == NULL);
181
assert(child->sibling == NULL);
183
child->parent = parent;
184
if (parent->last_child)
185
parent->last_child->sibling = child;
186
parent->last_child = child;
188
parent->child = child;
191
parent->iov_cnt += child->iov_cnt;
192
parent->str_len += child->str_len;
193
parent = parent->parent;
197
static bencode_item_t *__bencode_string_alloc(bencode_buffer_t *buf, const void *base,
198
int str_len, int iov_len, int iov_cnt, bencode_type_t type)
203
assert((str_len <= 99999) && (str_len >= 0));
204
ret = __bencode_item_alloc(buf, 7);
207
len_len = sprintf(ret->__buf, "%d:", str_len);
210
ret->iov[0].iov_base = ret->__buf;
211
ret->iov[0].iov_len = len_len;
212
ret->iov[1].iov_base = (void *) base;
213
ret->iov[1].iov_len = iov_len;
214
ret->iov_cnt = iov_cnt + 1;
215
ret->str_len = len_len + str_len;
220
bencode_item_t *bencode_string_len_dup(bencode_buffer_t *buf, const char *s, int len) {
221
char *sd = __bencode_alloc(buf, len);
225
return bencode_string_len(buf, sd, len);
228
bencode_item_t *bencode_string_len(bencode_buffer_t *buf, const char *s, int len) {
229
return __bencode_string_alloc(buf, s, len, len, 1, BENCODE_STRING);
232
bencode_item_t *bencode_string_iovec(bencode_buffer_t *buf, const struct iovec *iov, int iov_cnt, int str_len) {
239
for (i = 0; i < iov_cnt; i++)
240
str_len += iov[i].iov_len;
243
return __bencode_string_alloc(buf, iov, str_len, iov_cnt, iov_cnt, BENCODE_IOVEC);
246
bencode_item_t *bencode_integer(bencode_buffer_t *buf, long long int i) {
252
ret = __bencode_item_alloc(buf, alen + 3);
255
rlen = snprintf(ret->__buf, alen, "i%llde", i);
261
ret->type = BENCODE_INTEGER;
262
ret->iov[0].iov_base = ret->__buf;
263
ret->iov[0].iov_len = rlen;
264
ret->iov[1].iov_base = NULL;
265
ret->iov[1].iov_len = 0;
272
bencode_item_t *bencode_dictionary_add_len(bencode_item_t *dict, const char *key, int keylen, bencode_item_t *val) {
277
assert(dict->type == BENCODE_DICTIONARY);
279
str = bencode_string_len(dict->buffer, key, keylen);
282
__bencode_container_add(dict, str);
283
__bencode_container_add(dict, val);
287
bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item) {
290
assert(list->type == BENCODE_LIST);
291
__bencode_container_add(list, item);
295
static int __bencode_iovec_cpy(struct iovec *out, const struct iovec *in, int num) {
296
memcpy(out, in, num * sizeof(*out));
300
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
304
memcpy(out, in->iov_base, in->iov_len);
311
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
312
bencode_item_t *child;
313
struct iovec *orig = out;
315
assert(item->iov[0].iov_base != NULL);
316
out += __bencode_iovec_cpy(out, &item->iov[0], 1);
320
out += __bencode_iovec_dump(out, child);
321
child = child->sibling;
324
if (item->type == BENCODE_IOVEC)
325
out += __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
326
else if (item->iov[1].iov_base)
327
out += __bencode_iovec_cpy(out, &item->iov[1], 1);
329
assert((out - orig) == item->iov_cnt);
330
return item->iov_cnt;
333
static int __bencode_str_dump(char *out, bencode_item_t *item) {
335
bencode_item_t *child;
337
assert(item->iov[0].iov_base != NULL);
338
out += __bencode_str_cpy(out, &item->iov[0], 1);
342
out += __bencode_str_dump(out, child);
343
child = child->sibling;
346
if (item->type == BENCODE_IOVEC)
347
out += __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
348
else if (item->iov[1].iov_base)
349
out += __bencode_str_cpy(out, &item->iov[1], 1);
351
assert((out - orig) == item->str_len);
353
return item->str_len;
356
struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail) {
362
assert(root->iov_cnt > 0);
364
ret = __bencode_alloc(root->buffer, sizeof(*ret) * (root->iov_cnt + head + tail));
367
*cnt = __bencode_iovec_dump(ret + head, root);
371
char *bencode_collapse(bencode_item_t *root, int *len) {
377
assert(root->str_len > 0);
379
ret = __bencode_alloc(root->buffer, root->str_len + 1);
382
l = __bencode_str_dump(ret, root);
388
char *bencode_collapse_dup(bencode_item_t *root, int *len) {
394
assert(root->str_len > 0);
396
ret = BENCODE_MALLOC(root->str_len + 1);
400
l = __bencode_str_dump(ret, root);
406
static unsigned int __bencode_hash_str_len(const unsigned char *s, int len) {
411
if (len >= sizeof(*ul)) {
413
return *ul % BENCODE_HASH_BUCKETS;
415
if (len >= sizeof(*ui)) {
417
return *ui % BENCODE_HASH_BUCKETS;
419
if (len >= sizeof(*us)) {
421
return *us % BENCODE_HASH_BUCKETS;
423
if (len >= sizeof(*s))
424
return *s % BENCODE_HASH_BUCKETS;
429
static unsigned int __bencode_hash_str(bencode_item_t *str) {
430
assert(str->type == BENCODE_STRING);
431
return __bencode_hash_str_len(str->iov[1].iov_base, str->iov[1].iov_len);
434
static void __bencode_hash_insert(bencode_item_t *key, struct __bencode_hash *hash) {
435
unsigned int bucket, i;
437
i = bucket = __bencode_hash_str(key);
440
if (!hash->buckets[i]) {
441
hash->buckets[i] = key;
445
if (i >= BENCODE_HASH_BUCKETS)
452
static bencode_item_t *__bencode_decode_dictionary(bencode_buffer_t *buf, const char *s, const char *end) {
453
bencode_item_t *ret, *key, *value;
454
struct __bencode_hash *hash;
460
ret = __bencode_item_alloc(buf, sizeof(*hash));
463
__bencode_dictionary_init(ret);
465
hash = (void *) ret->__buf;
466
memset(hash, 0, sizeof(*hash));
469
key = __bencode_decode(buf, s, end);
473
if (key->type == BENCODE_END_MARKER)
475
if (key->type != BENCODE_STRING)
477
__bencode_container_add(ret, key);
481
value = __bencode_decode(buf, s, end);
485
if (value->type == BENCODE_END_MARKER)
487
__bencode_container_add(ret, value);
489
__bencode_hash_insert(key, hash);
495
static bencode_item_t *__bencode_decode_list(bencode_buffer_t *buf, const char *s, const char *end) {
496
bencode_item_t *ret, *item;
502
ret = __bencode_item_alloc(buf, 0);
505
__bencode_list_init(ret);
508
item = __bencode_decode(buf, s, end);
512
if (item->type == BENCODE_END_MARKER)
514
__bencode_container_add(ret, item);
520
static bencode_item_t *__bencode_decode_integer(bencode_buffer_t *buf, const char *s, const char *end) {
522
const char *orig = s;
539
i = strtoll(s, &convend, 10);
551
ret = __bencode_item_alloc(buf, 0);
554
ret->type = BENCODE_INTEGER;
555
ret->iov[0].iov_base = (void *) orig;
556
ret->iov[0].iov_len = s - orig;
557
ret->iov[1].iov_base = NULL;
558
ret->iov[1].iov_len = 0;
560
ret->str_len = s - orig;
566
static bencode_item_t *__bencode_decode_string(bencode_buffer_t *buf, const char *s, const char *end) {
567
unsigned long int sl;
569
const char *orig = s;
578
sl = strtoul(s, &convend, 10);
593
ret = __bencode_item_alloc(buf, 0);
596
ret->type = BENCODE_STRING;
597
ret->iov[0].iov_base = (void *) orig;
598
ret->iov[0].iov_len = s - orig;
599
ret->iov[1].iov_base = (void *) s;
600
ret->iov[1].iov_len = sl;
602
ret->str_len = s - orig + sl;
607
static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, const char *end) {
613
return __bencode_decode_dictionary(buf, s, end);
615
return __bencode_decode_list(buf, s, end);
617
return __bencode_decode_integer(buf, s, end);
619
return &__bencode_end_marker;
630
return __bencode_decode_string(buf, s, end);
636
bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) {
638
return __bencode_decode(buf, s, s + len);
642
static int __bencode_dictionary_key_match(bencode_item_t *key, const char *keystr, int keylen) {
643
assert(key->type == BENCODE_STRING);
645
if (keylen != key->iov[1].iov_len)
647
if (memcmp(keystr, key->iov[1].iov_base, keylen))
653
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) {
655
unsigned int bucket, i;
656
struct __bencode_hash *hash;
660
if (dict->type != BENCODE_DICTIONARY)
663
/* try hash lookup first if possible */
664
if (dict->value == 1) {
665
hash = (void *) dict->__buf;
666
i = bucket = __bencode_hash_str_len((const unsigned char *) keystr, keylen);
668
key = hash->buckets[i];
670
return NULL; /* would be there, but isn't */
671
assert(key->sibling != NULL);
672
if (__bencode_dictionary_key_match(key, keystr, keylen))
675
if (i >= BENCODE_HASH_BUCKETS)
678
break; /* fall back to regular lookup */
682
for (key = dict->child; key; key = key->sibling->sibling) {
683
assert(key->sibling != NULL);
684
if (__bencode_dictionary_key_match(key, keystr, keylen))
691
void bencode_buffer_destroy_add(bencode_buffer_t *buf, free_func_t func, void *p) {
692
struct __bencode_free_list *li;
696
li = __bencode_alloc(buf, sizeof(*li));
701
li->next = buf->free_list;