std::string read_until(InIt& in, InIt end, char end_token) { if (in == end) throw invalid_encoding(); std::string ret; while (*in != end_token) { ret += *in; ++in; if (in == end) throw invalid_encoding(); } return ret; }
std::string read_string(InIt& in, InIt end, int len) { assert(len >= 0); std::string ret; for (int i = 0; i < len; ++i) { if (in == end) throw invalid_encoding(); ret += *in; ++in; } return ret; }
entry bdecode(InIt start, InIt end) { try { entry e; detail::bdecode_recursive(start, end, e); return e; } catch(type_error&) { throw invalid_encoding(); } }
wchar_t UTF16Codec::get(SchemeObject* port) { istream* is = port->is; int32_t c = is->get(); if (c == -1 || c < 128) { return c; } else if ((c & LEN2_MASK) == LEN2_VAL) { c = c & FIVE_BIT_MASK; c |= is->get() & SIX_BIT_MASK; } else if ((c & LEN3_MASK) == LEN3_VAL) { c = c & FOUR_BIT_MASK; c = (c << 6) | (is->get() & SIX_BIT_MASK); c = (c << 6) | (is->get() & SIX_BIT_MASK); } else if ((c & LEN4_MASK) == LEN4_VAL) { c = c & THREE_BIT_MASK; c = (c << 6) | (is->get() & SIX_BIT_MASK); c = (c << 6) | (is->get() & SIX_BIT_MASK); c = (c << 6) | (is->get() & SIX_BIT_MASK); } else { throw invalid_encoding(); } return c; }
void bencode_recursive(OutIt& out, const entry& e) { switch(e.type()) { case entry::int_t: write_char(out, 'i'); write_integer(out, e.integer()); write_char(out, 'e'); break; case entry::string_t: write_integer(out, e.string().length()); write_char(out, ':'); write_string(out, e.string()); break; case entry::list_t: write_char(out, 'l'); for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) bencode_recursive(out, *i); write_char(out, 'e'); break; case entry::dictionary_t: write_char(out, 'd'); for (entry::dictionary_type::const_iterator i = e.dict().begin(); i != e.dict().end(); ++i) { // write key write_integer(out, i->first.length()); write_char(out, ':'); write_string(out, i->first); // write value bencode_recursive(out, i->second); } write_char(out, 'e'); break; default: throw invalid_encoding(); } }
void bdecode_recursive(InIt& in, InIt end, entry& ret) { if (in == end) throw invalid_encoding(); switch (*in) { // ---------------------------------------------- // integer case 'i': { ++in; // 'i' std::string val = read_until(in, end, 'e'); assert(*in == 'e'); ++in; // 'e' ret = entry(entry::int_t); ret.integer() = boost::lexical_cast<entry::integer_type>(val); } break; // ---------------------------------------------- // list case 'l': { ret = entry(entry::list_t); ++in; // 'l' while (*in != 'e') { ret.list().push_back(entry()); entry& e = ret.list().back(); bdecode_recursive(in, end, e); if (in == end) throw invalid_encoding(); } assert(*in == 'e'); ++in; // 'e' } break; // ---------------------------------------------- // dictionary case 'd': { ret = entry(entry::dictionary_t); ++in; // 'd' while (*in != 'e') { entry key; bdecode_recursive(in, end, key); entry& e = ret[key.string()]; bdecode_recursive(in, end, e); if (in == end) throw invalid_encoding(); } assert(*in == 'e'); ++in; // 'e' } break; // ---------------------------------------------- // string default: if (isdigit(*in)) { std::string len_s = read_until(in, end, ':'); assert(*in == ':'); ++in; // ':' int len = std::atoi(len_s.c_str()); ret = entry(entry::string_t); ret.string() = read_string(in, end, len); } else { throw invalid_encoding(); } } }