📄 benc_util.c.svn-base
字号:
break; } // error happened benc_obj_delete((benc_obj*) bobj_arr); return NULL;FoundArrayEnd: *dataInOut = data; *lenInOut = len; return bobj_arr;}static benc_dict *_parse_dict(const char** dataInOut, size_t* lenInOut){ char c; const char * data = *dataInOut; size_t len = *lenInOut; const char * key; size_t keyLen; benc_obj * val = NULL; benc_dict * dict = benc_dict_new(); if (!dict) return NULL; while (len > 0) { c = *data; if ('e' == c) { ++data; --len; goto FoundDictEnd; } keyLen = _parse_str_help(&data, &len); if (IVALID_LEN == keyLen) break; key = data; data += keyLen; len -= keyLen; assert(len > 0); val = _benc_obj_from_data(&data, &len, FALSE); if (!val) break; if (!benc_dict_insert(dict, key, keyLen, val)) break; } // error happened if (val) benc_obj_delete(val); benc_obj_delete((benc_obj*) dict); return NULL;FoundDictEnd: *dataInOut = data; *lenInOut = len; return dict;}static benc_obj *_benc_obj_from_data(const char** dataInOut, size_t* lenInOut, BOOL must_be_last){ char c; BOOL ok; int64_t int64val; benc_obj * bobj; const char * data = *dataInOut; size_t len = *lenInOut; /*assert(data);*/ /*assert(len > 0);*/ if (!data || (len <= 0)) return NULL; while (len >= 0) { c = *data++; --len; if ('i' == c) { ok = _parse_int64(&data, &len, &int64val); if (!ok) return NULL; bobj = (benc_obj*) benc_int64_new(int64val); break; } else if ('d' == c) { bobj = (benc_obj*) _parse_dict(&data, &len); break; } else if ('l' == c) { bobj = (benc_obj*) _parse_array(&data, &len); break; } else { /* must be string */ --data; ++len; bobj = (benc_obj*)_parse_str(&data, &len); break; } } if (bobj && must_be_last && (len > 0)) { benc_obj_delete(bobj); return NULL; } *dataInOut = data; *lenInOut = len; return bobj;}benc_obj *benc_obj_from_data(const char *data, size_t len){ return _benc_obj_from_data(&data, &len, TRUE);}static size_t _len_for_int64(benc_int64* bobj){ /* 2 is for "i" and "e" */ return 2 + digits_for_number(bobj->m_val);}static size_t _len_for_txt(const char* txt){ size_t txt_len = strlen(txt); return 1 + txt_len + digits_for_number(txt_len);}static size_t _len_for_str(benc_str* bobj){ /* 1 is for ":" */ return 1 + bobj->m_len + digits_for_number(bobj->m_len);}static size_t _len_for_array(benc_array* bobj){ size_t len = 2; benc_array_data *data = &(bobj->m_data); assert(BOT_ARRAY == bobj->m_type); while (data) { size_t i; benc_array_data *next = data->m_next; for (i=0; i < data->m_used; i++) { len += _benc_obj_to_data(data->m_data[i], PHASE_CALC_LEN, NULL); } data = next; } return len;}static size_t _len_for_dict(benc_dict* bobj){ size_t len = 2; benc_dict_data *data = &(bobj->m_data); assert(BOT_DICT == bobj->m_type); while (data) { size_t i; benc_dict_data *next = data->m_next; for (i=0; i < data->m_used; i++) { len += _len_for_txt(data->m_keys[i]); len += _benc_obj_to_data(data->m_values[i], PHASE_CALC_LEN, NULL); } data = next; } return len;}static void _str_reverse(char *start, char *end){ while (start < end) { char tmp = *start; *start++ = *end; *end-- = tmp; }}/* Convert 'val' to string in a buffer 'data' of size 'dataLen'. NULL-terminates the string. Returns FALSE if not enough space in the buffer. TODO: should return the size of needed buffer. TODO: for simplicity of code, if buffer is not big enough, will not use the last byte of the buffer TODO: move it to some other place like str_util.[h|c]?*/BOOL int64_to_string(int64_t val, char* data, size_t dataLen){ char * numStart; size_t dataLenRest = dataLen; if (val < 0) { if (dataLenRest < 2) { *data = 0; return FALSE; } *data++ = '-'; --dataLenRest; val = -val; } numStart = data; while (val > 9) { int digit = (int)(val % 10); if (dataLenRest < 2) { *data = 0; return FALSE; } *data++ = (char)(digit + '0'); --dataLenRest; val = val / 10; } if (dataLenRest < 2) { *data = 0; return FALSE; } data[0] = (char)(val + '0'); data[1] = 0; _str_reverse(numStart, data); return TRUE;}BOOL int64_to_string_zero_pad(int64_t val, size_t pad, char* data, size_t dataLen){ size_t len; assert(dataLen >= pad + 1); if (dataLen < pad + 1) return FALSE; if (!int64_to_string(val, data, dataLen)) return FALSE; len = strlen(data); if (len < pad) { size_t toPad = pad - len; size_t toMove = len + 1; memmove(data + toPad, data, toMove); while (toPad != 0) { data[toPad-1] = '0'; --toPad; } } return TRUE;}static size_t _serialize_int64_num(int64_t val, char* data){ char * numStart; size_t len; char * start = data; if (val < 0) { *data++ = '-'; val = -val; } numStart = data; while (val > 9) { int digit = (int)(val % 10); *data++ = (char)(digit + '0'); val = val / 10; } *data = (char)(val + '0'); _str_reverse(numStart, data); len = data + 1 - start; return len;}static size_t _serialize_int64(benc_int64* bobj, char* data){ size_t len; *data++ = 'i'; len = _serialize_int64_num(bobj->m_val, data); data += len; *data++ = 'e'; len += 2; assert(len == _len_for_int64(bobj)); return len;}static size_t _serialize_str_help(char *str, size_t strLen, char* data){ size_t len = _serialize_int64_num(strLen, data); data += len; *data++ = ':'; memcpy(data, str, strLen); return len + 1 + strLen;}static size_t _serialize_str(benc_str* bobj, char* data){ size_t len = _serialize_str_help(bobj->m_str, bobj->m_len, data); assert(len == _len_for_str(bobj)); return len;}static size_t _serialize_array(benc_array* arr, char* data){ int i; size_t len; int arr_len = benc_array_len(arr); char *start = data; *data++ = 'l'; for (i = 0; i < arr_len; i++) { benc_obj *bobj = benc_array_get(arr, i); size_t len_tmp = _benc_obj_to_data(bobj, PHASE_FORM_DATA, data); data += len_tmp; } *data++ = 'e'; len = data - start; assert(len == _len_for_array(arr)); return len;}static size_t _serialize_dict(benc_dict* dict, char* data){ benc_dict_data * curr; size_t len = 2; /* for 'd' and 'e' */ size_t i, lenTmp, used; *data++ = 'd'; curr = &(dict->m_data); assert(!curr->m_next); /* not using segments yet */ while (curr) { used = curr->m_used; for (i = 0; i < used; i++) { char *key = curr->m_keys[i]; benc_obj *val = curr->m_values[i]; lenTmp = _serialize_str_help(key, strlen(key), data); data += lenTmp; len += lenTmp; lenTmp = _benc_obj_to_data(val, PHASE_FORM_DATA, data); data += lenTmp; len += lenTmp; } curr = curr->m_next; } *data++ = 'e'; assert(len == _len_for_dict(dict)); return len;}static size_t _benc_obj_to_data(benc_obj* bobj, phase_t phase, char* data){ size_t len; assert((PHASE_CALC_LEN == phase) || (PHASE_FORM_DATA == phase)); assert((PHASE_CALC_LEN == phase) || data); if (BOT_INT64 == bobj->m_type) { if (PHASE_CALC_LEN == phase) len = _len_for_int64((benc_int64*)bobj); else len = _serialize_int64((benc_int64*)bobj, data); } else if (BOT_STRING == bobj->m_type) { if (PHASE_CALC_LEN == phase) len = _len_for_str((benc_str*)bobj); else len = _serialize_str((benc_str*)bobj, data); } else if (BOT_ARRAY == bobj->m_type) { if (PHASE_CALC_LEN == phase) len = _len_for_array((benc_array*)bobj); else len = _serialize_array((benc_array*)bobj, data); } else if (BOT_DICT == bobj->m_type) { if (PHASE_CALC_LEN == phase) len = _len_for_dict((benc_dict*)bobj); else len = _serialize_dict((benc_dict*)bobj, data); } else { assert(0); len = 0; } return len;}char * benc_obj_to_data(benc_obj *bobj, size_t* lenOut){ size_t len; char *data; assert(bobj); if (!bobj) return NULL; len = _benc_obj_to_data(bobj, PHASE_CALC_LEN, NULL); assert(len > 0); data = (char*)malloc(len+1); if (!data) return NULL; data[len] = 0; /* NULL-terminate to make life easier */ _benc_obj_to_data(bobj, PHASE_FORM_DATA, data); *lenOut = len; return data;}size_t benc_array_len(benc_array *bobj){ benc_array_data *data = (benc_array_data*) &(bobj->m_data); size_t len = data->m_used; while (data->m_next) { data = data->m_next; len += data->m_used; } return len; }benc_obj *benc_array_get(benc_array *bobj, size_t idx){ benc_array_data *data = (benc_array_data*) &(bobj->m_data); while (data) { if (idx < data->m_used) { return data->m_data[idx]; } idx -= data->m_used; data = data->m_next; } assert(0); /* asked for an non-existing item */ return NULL;}benc_int64* benc_obj_as_int64(benc_obj *bobj){ if (!bobj) return NULL; if (BOT_INT64 == bobj->m_type) return (benc_int64 *)bobj; return NULL;}benc_str* benc_obj_as_str(benc_obj *bobj){ if (!bobj) return NULL; if (BOT_STRING == bobj->m_type) return (benc_str *)bobj; return NULL;}benc_dict* benc_obj_as_dict(benc_obj *bobj){ if (!bobj) return NULL; if (BOT_DICT == bobj->m_type) return (benc_dict *)bobj; return NULL;}benc_array* benc_obj_as_array(benc_obj *bobj){ if (!bobj) return NULL; if (BOT_ARRAY == bobj->m_type) return (benc_array *)bobj; return NULL;}size_t benc_dict_len(benc_dict *bobj){ /* A hack, but works because benc_array and benc_dict share enough of common data layout */ return benc_array_len((benc_array*)bobj);}size_t benc_obj_len(benc_obj* bobj){ if (BOT_ARRAY == bobj->m_type) return benc_array_len((benc_array*)bobj); else if (BOT_DICT == bobj->m_type) return benc_dict_len((benc_dict*)bobj); else return -1;}void benc_array_delete(benc_array *bobj){ benc_array_data *data = &(bobj->m_data); assert(BOT_ARRAY == bobj->m_type); while (data) { size_t i; benc_array_data *next = data->m_next; for (i=0; i < data->m_used; i++) { benc_obj_delete(data->m_data[i]); } free(data->m_data); if (data != &(bobj->m_data)) { /* first m_data is within benc_array, but all others are heap allocated */ free(data); } data = next; }}static void benc_dict_delete(benc_dict *bobj){ benc_dict_data *data = &(bobj->m_data); assert(BOT_DICT == bobj->m_type); while (data) { size_t i; benc_dict_data *next = data->m_next; for (i=0; i < data->m_used; i++) { free(data->m_keys[i]); benc_obj_delete(data->m_values[i]); } free(data->m_values); free(data->m_keys); data = next; }}/* Release all memory used by bencoded object */void benc_obj_delete(benc_obj *bobj){ if (BOT_INT64 == bobj->m_type) { /* do nothing */ } else if (BOT_STRING == bobj->m_type) { benc_str *bobj_str = (benc_str*)bobj; free(bobj_str->m_str); } else if (BOT_ARRAY == bobj->m_type) { benc_array_delete((benc_array*)bobj); } else if (BOT_DICT == bobj->m_type) { benc_dict_delete((benc_dict*)bobj); } else { assert(0); } free(bobj);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -