int be_encode(be_node *node, char *str, int len) { size_t i; int loc = 0; switch (node->type) { case BE_STR: bd_snprintf(str, len, "%lli:", be_str_len(node)); loc += strlen(&(str[loc])); memcpy(&(str[loc]), node->val.s, be_str_len(node)); loc += be_str_len(node); break; case BE_INT: bd_snprintf(str, len, "i%llie", node->val.i); loc += strlen(&(str[loc])); break; case BE_LIST: snprintf(str, len, "l"); loc += 1; for (i = 0; node->val.l[i]; ++i) { loc += be_encode(node->val.l[i], &(str[loc]), len-loc); } snprintf(&(str[loc]), len - loc, "e"); loc += 1; break; case BE_DICT: snprintf(str, len, "d"); loc += 1; for (i = 0; node->val.d[i].val; ++i) { /* assumption that key must be ascii! */ snprintf(&(str[loc]), len-loc, "%i:%s", (int) strlen(node->val.d[i].key), node->val.d[i].key); loc += strlen(&(str[loc])); loc += be_encode(node->val.d[i].val, &(str[loc]), len-loc); } snprintf(&(str[loc]), len - loc, "e"); loc += 1; break; } return loc; }
unsigned char *be_encode(bencode_t *bencode, size_t *size) { unsigned char *buf; unsigned int length; // size of buf without '\0' switch(bencode->type) { case BE_INTEGER: //printf("int\t%d\n", *(bencode->n)); length = (unsigned int)log10((double)*bencode->n) + 1; //printf("length=%d\n", length); buf = (unsigned char *)malloc(sizeof(char) * (length + 3)); // 3: 'i', 'e', '\0' sprintf(buf, "i%de", *bencode->n); length += 2; // 2: 'e', 'i' buf[length] = '\0'; break; case BE_STRING: //printf("str\n"); { int digits; length = bencode->str->length; digits = (int)log10((double)length) + 1; buf = (unsigned char *)malloc(sizeof(char) * (length + digits + 2)); // 2: ':', '\0' sprintf(buf, "%d:", length); memcpy(buf + digits + 1, bencode->str->data, length); // 1: ':'a length += digits + 1; // 1: ':' buf[length] = '\0'; } break; case BE_LIST: //printf("list\n"); { list_t *list; unsigned char *buf1; size_t buf_size = 512; // current size of allocated memory for buf size_t buf1_size = 0; length = 0; list = bencode->list; buf = (unsigned char *)malloc(sizeof(char) * buf_size); *buf = 'l'; length++; while(list) { buf1 = be_encode(list->bencode, &buf1_size); while(length + buf1_size + 1 > buf_size) { // 1: '\0' buf_size *= 2; buf = (unsigned char*)realloc(buf, sizeof(char) * buf_size); } memcpy(buf + length, buf1, buf1_size); length += buf1_size; free(buf1); list = list->next; } length += 1; // 1: 'e' buf = (unsigned char *)realloc(buf, sizeof(char) * (length + 1)); // 1:'\0' buf[length - 1] = 'e'; buf[length] = '\0'; //printf("list\tend:%d\t\t[%s]\n", length, buf); } break; case BE_DICT: //printf("dict\n"); { list_t *dict; unsigned char *buf1; unsigned char *buf2; size_t buf_size = 512; // current size of allocated memory for buf size_t buf1_size = 0; size_t buf2_size = 0; length = 0; dict = bencode->dict; buf = (unsigned char *)malloc(sizeof(char) * buf_size); *buf = 'd'; length++; while(dict) { buf1 = be_encode(dict->bencode + 0, &buf1_size); //printf("dict\tbuf1\t%s\n", buf1); buf2 = be_encode(dict->bencode + 1, &buf2_size); //printf("dict\tbuf2\t%s\n", buf2); while(length + buf1_size + buf2_size + 1 > buf_size) { // 1: '\0' buf_size *= 2; buf = (unsigned char*)realloc(buf, sizeof(char) * buf_size); } memcpy(buf + length, buf1, buf1_size); length += buf1_size; memcpy(buf + length, buf2, buf2_size); length += buf2_size; free(buf1); free(buf2); dict = dict->next; } length += 1; // 1: 'e' buf = (unsigned char *)realloc(buf, sizeof(char) * (length + 1)); // 1: '\0' buf[length - 1] = 'e'; buf[length] = '\0'; //printf("dict\tend:%d\t\t{%s}\n", length, buf); } break; default: //printf("\n\n\n\ndefault\t%d\n\n\n\n", bencode->type); return NULL; } if(size != NULL) { *size = length; } return buf; }