String* VersionList_stringify(struct VersionList* list, struct Allocator* alloc) { uint8_t numberSize = 1; uint32_t max = 0xff; for (int i = 0; i < (int)list->length; i++) { while (list->versions[i] >= max) { numberSize++; max = max << 8 | 0xff; } } String* out = String_newBinary(NULL, (numberSize * list->length + 1), alloc); struct Writer* w = ArrayWriter_new(out->bytes, out->len, alloc); Writer_write(w, &numberSize, 1); for (int i = 0; i < (int)list->length; i++) { uint32_t ver = list->versions[i] << ((4-numberSize) * 8); ver = Endian_hostToBigEndian32(ver); Writer_write(w, (uint8_t*) &ver, numberSize); } Writer_write(w, &numberSize, 1); return out; }
/** @see BencSerializer.h */ static int32_t serializeString(struct Writer* writer, const String* string) { writeint64_t(writer, string->len); Writer_write(writer, ":", 1); return Writer_write(writer, string->bytes, string->len); }
/** @see BencSerializer.h */ static int32_t serializeint64_t(struct Writer* writer, int64_t integer) { Writer_write(writer, "i", 1); writeint64_t(writer, integer); return Writer_write(writer, "e", 1); }
/** @see BencSerializer.h */ static int32_t serializeDictionary(struct Writer* writer, const Dict* dictionary) { const struct Dict_Entry* entry = *dictionary; Writer_write(writer, "d", 1); while (entry != NULL) { serializeString(writer, entry->key); serializeGeneric(writer, entry->val); entry = entry->next; } return Writer_write(writer, "e", 1); }
/** * Helper function for writing an integer into a writer in base 10 format. * * @param writer the place to write the integer to. * @param integer the number to write. */ static int32_t writeint64_t(struct Writer* writer, int64_t integer) { char buffer[32] = {0}; snprintf(buffer, 32, "%" PRId64, integer); return Writer_write(writer, buffer, CString_strlen(buffer)); }
/** @see BencSerializer.h */ static int32_t serializeList(struct Writer* writer, const List* list) { int ret = Writer_write(writer, "l", 1); if (list) { const struct List_Item* entry = *list; while (ret == 0 && entry != NULL) { ret = serializeGeneric(writer, entry->elem); entry = entry->next; } } if (ret == 0) { ret = Writer_write(writer, "e", 1); } return ret; }
void testParse(struct Writer* w, struct Reader* r, struct Allocator* alloc) { char* badBenc = "d2:aq21:RouterModule_pingNode4:argsd4:path39:fcd9:6a75:6c9c7:timeouti4000ee" "6:cookie0:4:hash64:09c6bcd1482df339757c99bbc5e796192968a28562f701fb53a57ed6" "e26b15511:q4:auth4:txid19:43866780dc455e15619e"; Writer_write(w, badBenc, strlen(badBenc)+1); Dict dict; Assert_always(StandardBencSerializer_get()->parseDictionary(r, alloc, &dict)); }
/** @see BencSerializer.h */ static int32_t serializeint64_t(struct Writer* writer, int64_t integer) { char buffer[32]; Bits_memset(buffer, 0, 32); snprintf(buffer, 32, "%" PRId64, integer); return Writer_write(writer, buffer, strlen(buffer)); }
/** @see BencSerializer.h */ static int32_t serializeString(struct Writer* writer, const String* string) { Writer_write(writer, "\"", 1); size_t i; uint8_t chr; char buffer[4]; for (i = 0; i < string->len; i++) { chr = (uint8_t) string->bytes[i] & 0xFF; /* Nonprinting chars, \ and " are hex'd */ if (chr < 126 && chr > 31 && chr != '\\' && chr != '"') { snprintf(buffer, 4, "%c", chr); Writer_write(writer, buffer, 1); } else { snprintf(buffer, 4, "\\x%.2X", chr); Writer_write(writer, buffer, 4); } } return Writer_write(writer, "\"", 1); }
/** * Serialize a bencoded dictionary with padding before each line. * * @param writer the place to write the output to. * @param padSpaceCount the number of spaces to place at the beginning of each line. * @param dictionary the dictionary to serialize. */ static int32_t serializeDictionaryWithPadding(struct Writer* writer, size_t padSpaceCount, const Dict* dictionary) { int padCounter = 0; Writer_write(writer, "{\n", 2); const struct Dict_Entry* entry = *dictionary; while (entry != NULL) { PAD(padSpaceCount + 2, padCounter, writer); serializeString(writer, entry->key); Writer_write(writer, " : ", 3); serializeGenericWithPadding(writer, padSpaceCount + 2, entry->val); entry = entry->next; if (entry != NULL) { Writer_write(writer, ",\n", 2); } } Writer_write(writer, "\n", 1); PAD(padSpaceCount, padCounter, writer); return Writer_write(writer, "}", 1); }
/** * Serialize a bencoded list with padding at the beginning of each line. * * @param writer the place to write the output to. * @param padSpaceCount the number of spaces to place at the beginning of each line. * @param list the list to serialize */ static int32_t serializeListWithPadding(struct Writer* writer, const size_t padSpaceCount, const List* list) { int padCounter; Writer_write(writer, "[\n", 2); const struct List_Item* entry = *list; while (entry != NULL) { PAD(padSpaceCount + 2, padCounter, writer); serializeGenericWithPadding(writer, padSpaceCount + 2, entry->elem); entry = entry->next; if (entry != NULL) { Writer_write(writer, ",\n", 2); } } Writer_write(writer, "\n", 1); PAD(padSpaceCount, padCounter, writer); return Writer_write(writer, "]", 1); }