|
|
|
|
@ -47,7 +47,7 @@ static bencode_item_t *__bencode_decode(bencode_buffer_t *buf, const char *s, co
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void __bencode_item_init(bencode_item_t *item) {
|
|
|
|
|
item->parent = item->child = item->sibling = NULL;
|
|
|
|
|
item->last_child = item->parent = item->child = item->sibling = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __bencode_container_init(bencode_item_t *cont) {
|
|
|
|
|
@ -179,8 +179,11 @@ static void __bencode_container_add(bencode_item_t *parent, bencode_item_t *chil
|
|
|
|
|
assert(child->sibling == NULL);
|
|
|
|
|
|
|
|
|
|
child->parent = parent;
|
|
|
|
|
child->sibling = parent->child;
|
|
|
|
|
parent->child = child;
|
|
|
|
|
if (parent->last_child)
|
|
|
|
|
parent->last_child->sibling = child;
|
|
|
|
|
parent->last_child = child;
|
|
|
|
|
if (!parent->child)
|
|
|
|
|
parent->child = child;
|
|
|
|
|
|
|
|
|
|
while (parent) {
|
|
|
|
|
parent->iov_cnt += child->iov_cnt;
|
|
|
|
|
@ -288,91 +291,66 @@ bencode_item_t *bencode_list_add(bencode_item_t *list, bencode_item_t *item) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_iovec_cpy(struct iovec *out, const struct iovec *in, int num) {
|
|
|
|
|
out -= num;
|
|
|
|
|
memcpy(out, in, num * sizeof(*out));
|
|
|
|
|
return num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_iovec_dump_rev(struct iovec *out, bencode_item_t *item) {
|
|
|
|
|
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
|
|
|
|
|
char *orig = out;
|
|
|
|
|
|
|
|
|
|
while (--num >= 0) {
|
|
|
|
|
memcpy(out, in->iov_base, in->iov_len);
|
|
|
|
|
out += in->iov_len;
|
|
|
|
|
in++;
|
|
|
|
|
}
|
|
|
|
|
return out - orig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
|
|
|
|
|
bencode_item_t *child;
|
|
|
|
|
struct iovec *orig = out;
|
|
|
|
|
|
|
|
|
|
if (item->type == BENCODE_IOVEC)
|
|
|
|
|
out -= __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
|
|
|
|
|
else if (item->iov[1].iov_base)
|
|
|
|
|
out -= __bencode_iovec_cpy(out, &item->iov[1], 1);
|
|
|
|
|
assert(item->iov[0].iov_base != NULL);
|
|
|
|
|
out += __bencode_iovec_cpy(out, &item->iov[0], 1);
|
|
|
|
|
|
|
|
|
|
child = item->child;
|
|
|
|
|
while (child) {
|
|
|
|
|
out -= __bencode_iovec_dump_rev(out, child);
|
|
|
|
|
out += __bencode_iovec_dump(out, child);
|
|
|
|
|
child = child->sibling;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(item->iov[0].iov_base != NULL);
|
|
|
|
|
out -= __bencode_iovec_cpy(out, &item->iov[0], 1);
|
|
|
|
|
if (item->type == BENCODE_IOVEC)
|
|
|
|
|
out += __bencode_iovec_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
|
|
|
|
|
else if (item->iov[1].iov_base)
|
|
|
|
|
out += __bencode_iovec_cpy(out, &item->iov[1], 1);
|
|
|
|
|
|
|
|
|
|
assert((orig - out) == item->iov_cnt);
|
|
|
|
|
assert((out - orig) == item->iov_cnt);
|
|
|
|
|
return item->iov_cnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_str_cpy(char *out, const struct iovec *in, int num) {
|
|
|
|
|
static int __bencode_str_dump(char *out, bencode_item_t *item) {
|
|
|
|
|
char *orig = out;
|
|
|
|
|
|
|
|
|
|
in += num;
|
|
|
|
|
while (--num >= 0) {
|
|
|
|
|
in--;
|
|
|
|
|
out -= in->iov_len;
|
|
|
|
|
memcpy(out, in->iov_base, in->iov_len);
|
|
|
|
|
}
|
|
|
|
|
return orig - out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_str_dump_rev(char *out, bencode_item_t *item) {
|
|
|
|
|
bencode_item_t *child;
|
|
|
|
|
char *orig = out;
|
|
|
|
|
|
|
|
|
|
if (item->type == BENCODE_IOVEC)
|
|
|
|
|
out -= __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
|
|
|
|
|
else if (item->iov[1].iov_base)
|
|
|
|
|
out -= __bencode_str_cpy(out, &item->iov[1], 1);
|
|
|
|
|
assert(item->iov[0].iov_base != NULL);
|
|
|
|
|
out += __bencode_str_cpy(out, &item->iov[0], 1);
|
|
|
|
|
|
|
|
|
|
child = item->child;
|
|
|
|
|
while (child) {
|
|
|
|
|
out -= __bencode_str_dump_rev(out, child);
|
|
|
|
|
out += __bencode_str_dump(out, child);
|
|
|
|
|
child = child->sibling;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(item->iov[0].iov_base != NULL);
|
|
|
|
|
out -= __bencode_str_cpy(out, &item->iov[0], 1);
|
|
|
|
|
if (item->type == BENCODE_IOVEC)
|
|
|
|
|
out += __bencode_str_cpy(out, item->iov[1].iov_base, item->iov[1].iov_len);
|
|
|
|
|
else if (item->iov[1].iov_base)
|
|
|
|
|
out += __bencode_str_cpy(out, &item->iov[1], 1);
|
|
|
|
|
|
|
|
|
|
assert((orig - out) == item->str_len);
|
|
|
|
|
assert((out - orig) == item->str_len);
|
|
|
|
|
*out = '\0';
|
|
|
|
|
return item->str_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_iovec_dump(struct iovec *out, bencode_item_t *item) {
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
/* sibling lists are built in reverse, so dump everything
|
|
|
|
|
out backwards, end to start */
|
|
|
|
|
out += item->iov_cnt;
|
|
|
|
|
len = __bencode_iovec_dump_rev(out, item);
|
|
|
|
|
assert(len == item->iov_cnt);
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __bencode_str_dump(char *out, bencode_item_t *item) {
|
|
|
|
|
int len;
|
|
|
|
|
char *orig = out;
|
|
|
|
|
|
|
|
|
|
/* sibling lists are built in reverse, so dump everything
|
|
|
|
|
out backwards, end to start */
|
|
|
|
|
out += item->str_len;
|
|
|
|
|
len = __bencode_str_dump_rev(out, item);
|
|
|
|
|
assert(len == item->str_len);
|
|
|
|
|
orig[len] = '\0';
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct iovec *bencode_iovec(bencode_item_t *root, int *cnt, unsigned int head, unsigned int tail) {
|
|
|
|
|
struct iovec *ret;
|
|
|
|
|
|
|
|
|
|
@ -451,14 +429,14 @@ static unsigned int __bencode_hash_str(bencode_item_t *str) {
|
|
|
|
|
return __bencode_hash_str_len(str->iov[1].iov_base, str->iov[1].iov_len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __bencode_hash_insert(bencode_item_t *key, bencode_item_t *value, struct __bencode_hash *hash) {
|
|
|
|
|
static void __bencode_hash_insert(bencode_item_t *key, struct __bencode_hash *hash) {
|
|
|
|
|
unsigned int bucket, i;
|
|
|
|
|
|
|
|
|
|
i = bucket = __bencode_hash_str(key);
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
if (!hash->buckets[i]) {
|
|
|
|
|
hash->buckets[i] = value;
|
|
|
|
|
hash->buckets[i] = key;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
@ -506,7 +484,7 @@ static bencode_item_t *__bencode_decode_dictionary(bencode_buffer_t *buf, const
|
|
|
|
|
return NULL;
|
|
|
|
|
__bencode_container_add(ret, value);
|
|
|
|
|
|
|
|
|
|
__bencode_hash_insert(key, value, hash);
|
|
|
|
|
__bencode_hash_insert(key, hash);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
@ -659,23 +637,19 @@ bencode_item_t *bencode_decode(bencode_buffer_t *buf, const char *s, int len) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bencode_item_t *__bencode_dictionary_key_test(bencode_item_t *val, const char *keystr, int keylen) {
|
|
|
|
|
bencode_item_t *key;
|
|
|
|
|
|
|
|
|
|
key = val->sibling;
|
|
|
|
|
assert(key != NULL);
|
|
|
|
|
static int __bencode_dictionary_key_match(bencode_item_t *key, const char *keystr, int keylen) {
|
|
|
|
|
assert(key->type == BENCODE_STRING);
|
|
|
|
|
|
|
|
|
|
if (keylen != key->iov[1].iov_len)
|
|
|
|
|
return key;
|
|
|
|
|
return 0;
|
|
|
|
|
if (memcmp(keystr, key->iov[1].iov_base, keylen))
|
|
|
|
|
return key;
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *keystr, int keylen) {
|
|
|
|
|
bencode_item_t *key, *val;
|
|
|
|
|
bencode_item_t *key;
|
|
|
|
|
unsigned int bucket, i;
|
|
|
|
|
struct __bencode_hash *hash;
|
|
|
|
|
|
|
|
|
|
@ -689,12 +663,12 @@ bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key
|
|
|
|
|
hash = (void *) dict->__buf;
|
|
|
|
|
i = bucket = __bencode_hash_str_len((const unsigned char *) keystr, keylen);
|
|
|
|
|
while (1) {
|
|
|
|
|
val = hash->buckets[i];
|
|
|
|
|
if (!val)
|
|
|
|
|
return NULL; /* would be there, but isn't */
|
|
|
|
|
key = __bencode_dictionary_key_test(val, keystr, keylen);
|
|
|
|
|
key = hash->buckets[i];
|
|
|
|
|
if (!key)
|
|
|
|
|
return val;
|
|
|
|
|
return NULL; /* would be there, but isn't */
|
|
|
|
|
assert(key->sibling != NULL);
|
|
|
|
|
if (__bencode_dictionary_key_match(key, keystr, keylen))
|
|
|
|
|
return key->sibling;
|
|
|
|
|
i++;
|
|
|
|
|
if (i >= BENCODE_HASH_BUCKETS)
|
|
|
|
|
i = 0;
|
|
|
|
|
@ -703,10 +677,10 @@ bencode_item_t *bencode_dictionary_get_len(bencode_item_t *dict, const char *key
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (val = dict->child; val; val = key->sibling) {
|
|
|
|
|
key = __bencode_dictionary_key_test(val, keystr, keylen);
|
|
|
|
|
if (!key)
|
|
|
|
|
return val;
|
|
|
|
|
for (key = dict->child; key; key = key->sibling->sibling) {
|
|
|
|
|
assert(key->sibling != NULL);
|
|
|
|
|
if (__bencode_dictionary_key_match(key, keystr, keylen))
|
|
|
|
|
return key->sibling;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|