diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-11-05 12:01:57 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-11-05 12:01:57 +0900 |
| commit | d1d49036651012433595357ca31e6f65dbec3a6b (patch) | |
| tree | a962461fc219fa02458d154eef4e3a354bb99e40 /src | |
| parent | d305432ec0015cfc9479331531a78f29c398bd8c (diff) | |
Rewritten bencode2::decode functions
Diffstat (limited to 'src')
| -rw-r--r-- | src/DHTMessageReceiver.cc | 2 | ||||
| -rw-r--r-- | src/DefaultBtAnnounce.cc | 2 | ||||
| -rw-r--r-- | src/DefaultExtensionMessageFactory.cc | 3 | ||||
| -rw-r--r-- | src/FtpConnection.cc | 2 | ||||
| -rw-r--r-- | src/HandshakeExtensionMessage.cc | 2 | ||||
| -rw-r--r-- | src/HttpServer.cc | 7 | ||||
| -rw-r--r-- | src/OptionParser.cc | 2 | ||||
| -rw-r--r-- | src/ParameterizedStringParser.cc | 2 | ||||
| -rw-r--r-- | src/UTPexExtensionMessage.cc | 2 | ||||
| -rw-r--r-- | src/bencode2.cc | 189 | ||||
| -rw-r--r-- | src/bencode2.h | 25 | ||||
| -rw-r--r-- | src/bittorrent_helper.cc | 8 | ||||
| -rw-r--r-- | src/util.h | 13 |
13 files changed, 149 insertions, 110 deletions
diff --git a/src/DHTMessageReceiver.cc b/src/DHTMessageReceiver.cc index e5558d9d..8b2b98b1 100644 --- a/src/DHTMessageReceiver.cc +++ b/src/DHTMessageReceiver.cc @@ -76,7 +76,7 @@ SharedHandle<DHTMessage> DHTMessageReceiver::receiveMessage() return SharedHandle<DHTMessage>(); } bool isReply = false; - SharedHandle<ValueBase> decoded = bencode2::decode(data, length); + SharedHandle<ValueBase> decoded = bencode2::decode(data, data+length); const Dict* dict = downcast<Dict>(decoded); if(dict) { const String* y = downcast<String>(dict->get(DHTMessage::Y)); diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index 62ba3646..43778ab6 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -220,7 +220,7 @@ DefaultBtAnnounce::processAnnounceResponse(const unsigned char* trackerResponse, { A2_LOG_DEBUG("Now processing tracker response."); SharedHandle<ValueBase> decodedValue = - bencode2::decode(trackerResponse, trackerResponseLength); + bencode2::decode(trackerResponse, trackerResponse+trackerResponseLength); const Dict* dict = downcast<Dict>(decodedValue); if(!dict) { throw DL_ABORT_EX(MSG_NULL_TRACKER_RESPONSE); diff --git a/src/DefaultExtensionMessageFactory.cc b/src/DefaultExtensionMessageFactory.cc index 3d3f9b36..47fa26b3 100644 --- a/src/DefaultExtensionMessageFactory.cc +++ b/src/DefaultExtensionMessageFactory.cc @@ -101,7 +101,8 @@ DefaultExtensionMessageFactory::createMessage(const unsigned char* data, size_t static_cast<unsigned long>(length))); } size_t end; - SharedHandle<ValueBase> decoded = bencode2::decode(data+1, length-1, end); + SharedHandle<ValueBase> decoded = + bencode2::decode(data+1, data+length, end); const Dict* dict = downcast<Dict>(decoded); if(!dict) { throw DL_ABORT_EX("Bad ut_metadata: dictionary not found"); diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index d6cd94f0..9fc3ac80 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -435,7 +435,7 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size) std::pair<unsigned int, std::string> response; if(bulkReceiveResponse(response)) { if(response.first == 213) { - std::pair<Scip, Scip> rp; + std::pair<Sip, Sip> rp; util::divide(rp, response.second.begin(), response.second.end(), ' '); size = util::parseULLInt(rp.second.first, rp.second.second); } diff --git a/src/HandshakeExtensionMessage.cc b/src/HandshakeExtensionMessage.cc index cec3ea2d..3fae69d8 100644 --- a/src/HandshakeExtensionMessage.cc +++ b/src/HandshakeExtensionMessage.cc @@ -173,7 +173,7 @@ HandshakeExtensionMessage::create(const unsigned char* data, size_t length) HandshakeExtensionMessageHandle msg(new HandshakeExtensionMessage()); A2_LOG_DEBUG(fmt("Creating HandshakeExtensionMessage from %s", util::percentEncode(data, length).c_str())); - SharedHandle<ValueBase> decoded = bencode2::decode(data+1, length-1); + SharedHandle<ValueBase> decoded = bencode2::decode(data+1, data+length); const Dict* dict = downcast<Dict>(decoded); if(!dict) { throw DL_ABORT_EX diff --git a/src/HttpServer.cc b/src/HttpServer.cc index cef02a80..318635c6 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -227,10 +227,11 @@ bool HttpServer::authenticate() } std::string userpass = Base64::decode(std::string(p.second.first, p.second.second)); - util::divide(p, userpass.begin(), userpass.end(), ':'); - return util::streq(p.first.first, p.first.second, + std::pair<Sip, Sip> up; + util::divide(up, userpass.begin(), userpass.end(), ':'); + return util::streq(up.first.first, up.first.second, username_.begin(), username_.end()) && - util::streq(p.second.first, p.second.second, + util::streq(up.second.first, up.second.second, password_.begin(), password_.end()); } diff --git a/src/OptionParser.cc b/src/OptionParser.cc index 157d2adc..a1e4090d 100644 --- a/src/OptionParser.cc +++ b/src/OptionParser.cc @@ -184,7 +184,7 @@ void OptionParser::parse(Option& option, std::istream& is) const if(line.empty() || line[0] == '#') { continue; } - std::pair<Scip, Scip> nv; + std::pair<Sip, Sip> nv; util::divide(nv, line.begin(), line.end(), '='); if(nv.first.first == nv.first.second) { continue; diff --git a/src/ParameterizedStringParser.cc b/src/ParameterizedStringParser.cc index 2b80d41b..579881fa 100644 --- a/src/ParameterizedStringParser.cc +++ b/src/ParameterizedStringParser.cc @@ -124,7 +124,7 @@ ParameterizedStringParser::createLoop(const std::string& src, int& offset) } loopStr.erase(colonIndex); } - std::pair<Scip, Scip> range; + std::pair<Sip, Sip> range; util::divide(range, loopStr.begin(), loopStr.end(), '-'); if(range.first.first == range.first.second || range.second.first == range.second.second) { diff --git a/src/UTPexExtensionMessage.cc b/src/UTPexExtensionMessage.cc index a974d8f2..fe0e99c6 100644 --- a/src/UTPexExtensionMessage.cc +++ b/src/UTPexExtensionMessage.cc @@ -190,7 +190,7 @@ UTPexExtensionMessage::create(const unsigned char* data, size_t len) } UTPexExtensionMessageHandle msg(new UTPexExtensionMessage(*data)); - SharedHandle<ValueBase> decoded = bencode2::decode(data+1, len-1); + SharedHandle<ValueBase> decoded = bencode2::decode(data+1, data+len); const Dict* dict = downcast<Dict>(decoded); if(dict) { const String* added = downcast<String>(dict->get("added")); diff --git a/src/bencode2.cc b/src/bencode2.cc index 181309a8..1db0ddbe 100644 --- a/src/bencode2.cc +++ b/src/bencode2.cc @@ -40,90 +40,92 @@ #include "DlAbortEx.h" #include "error_code.h" #include "BufferedFile.h" +#include "util.h" namespace aria2 { namespace bencode2 { namespace { -SharedHandle<ValueBase> decodeiter(std::istream& ss, size_t depth); +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodeiter +(InputIterator first, + InputIterator last, + size_t depth); } // namespace namespace { -void checkdelim(std::istream& ss, const char delim = ':') +template<typename InputIterator> +std::pair<std::string, InputIterator> +decoderawstring(InputIterator first, InputIterator last) { - char d; - if(!(ss.get(d) && d == delim)) { - throw DL_ABORT_EX2 - (fmt("Bencode decoding failed: Delimiter '%c' not found.", - delim), - error_code::BENCODE_PARSE_ERROR); - } -} -} // namespace - -namespace { -std::string decoderawstring(std::istream& ss) -{ - int length; - ss >> length; - if(!ss || length < 0) { + InputIterator i = first; + int32_t len; + for(; i != last && *i != ':'; ++i); + if(i == last || i == first || !util::parseIntNoThrow(len, first, i) || + len < 0) { throw DL_ABORT_EX2("Bencode decoding failed:" " A positive integer expected but none found.", error_code::BENCODE_PARSE_ERROR); } - // TODO check length, it must be less than or equal to INT_MAX - checkdelim(ss); - char* buf = new char[length]; - ss.read(buf, length); - std::string str(&buf[0], &buf[length]); - delete [] buf; - if(ss.gcount() != static_cast<int>(length)) { + ++i; + if(last-i < len) { throw DL_ABORT_EX2 (fmt("Bencode decoding failed:" - " Expected %lu bytes of data, but only %ld read.", - static_cast<unsigned long>(length), - static_cast<long int>(ss.gcount())), + " Expected %d bytes of data, but only %d read.", + len, static_cast<int>(last-i)), error_code::BENCODE_PARSE_ERROR); } - return str; + return std::make_pair(std::string(i, i+len), i+len); } } // namespace namespace { -SharedHandle<ValueBase> decodestring(std::istream& ss) +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodestring(InputIterator first, InputIterator last) { - return String::g(decoderawstring(ss)); + std::pair<std::string, InputIterator> r = decoderawstring(first, last); + return std::make_pair(String::g(r.first), r.second); } } // namespace namespace { -SharedHandle<ValueBase> decodeinteger(std::istream& ss) +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodeinteger(InputIterator first, InputIterator last) { + InputIterator i = first; + for(; i != last && *i != 'e'; ++i); Integer::ValueType iv; - ss >> iv; - if(!ss) { + if(i == last || !util::parseLLIntNoThrow(iv, first, i)) { throw DL_ABORT_EX2("Bencode decoding failed:" " Integer expected but none found", error_code::BENCODE_PARSE_ERROR); } - checkdelim(ss, 'e'); - return Integer::g(iv); + return std::make_pair(Integer::g(iv), ++i); } } // namespace namespace { -SharedHandle<ValueBase> decodedict(std::istream& ss, size_t depth) +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodedict +(InputIterator first, + InputIterator last, + size_t depth) { SharedHandle<Dict> dict = Dict::g(); - char c; - while(ss.get(c)) { - if(c == 'e') { - return dict; + while(first != last) { + if(*first == 'e') { + return std::make_pair(dict, ++first); } else { - ss.unget(); - std::string key = decoderawstring(ss); - dict->put(key, decodeiter(ss, depth)); + std::pair<std::string, InputIterator> keyp = decoderawstring(first, last); + std::pair<SharedHandle<ValueBase>, InputIterator> r = + decodeiter(keyp.second, last, depth); + dict->put(keyp.first, r.first); + first = r.second; } } throw DL_ABORT_EX2("Bencode decoding failed:" @@ -133,16 +135,22 @@ SharedHandle<ValueBase> decodedict(std::istream& ss, size_t depth) } // namespace namespace { -SharedHandle<ValueBase> decodelist(std::istream& ss, size_t depth) +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodelist +(InputIterator first, + InputIterator last, + size_t depth) { SharedHandle<List> list = List::g(); - char c; - while(ss.get(c)) { - if(c == 'e') { - return list; + while(first != last) { + if(*first == 'e') { + return std::make_pair(list, ++first); } else { - ss.unget(); - list->append(decodeiter(ss, depth)); + std::pair<SharedHandle<ValueBase>, InputIterator> r = + decodeiter(first, last, depth); + list->append(r.first); + first = r.second; } } throw DL_ABORT_EX2("Bencode decoding failed:" @@ -162,60 +170,79 @@ void checkDepth(size_t depth) } // namespace namespace { -SharedHandle<ValueBase> decodeiter(std::istream& ss, size_t depth) +template<typename InputIterator> +std::pair<SharedHandle<ValueBase>, InputIterator> +decodeiter +(InputIterator first, + InputIterator last, + size_t depth) { checkDepth(depth); - char c; - if(!ss.get(c)) { + if(first == last) { throw DL_ABORT_EX2("Bencode decoding failed:" " Unexpected EOF in term context." " 'd', 'l', 'i' or digit is expected.", error_code::BENCODE_PARSE_ERROR); } - if(c == 'd') { - return decodedict(ss, depth+1); - } else if(c == 'l') { - return decodelist(ss, depth+1); - } else if(c == 'i') { - return decodeinteger(ss); + if(*first == 'd') { + return decodedict(++first, last, depth+1); + } else if(*first == 'l') { + return decodelist(++first, last, depth+1); + } else if(*first == 'i') { + return decodeinteger(++first, last); } else { - ss.unget(); - return decodestring(ss); + return decodestring(first, last); } } } // namespace -SharedHandle<ValueBase> decode(std::istream& in) +namespace { +template<typename InputIterator> +SharedHandle<ValueBase> decodegen +(InputIterator first, + InputIterator last, + size_t& end) { - return decodeiter(in, 0); + if(first == last) { + return SharedHandle<ValueBase>(); + } + std::pair<SharedHandle<ValueBase>, InputIterator> p = + decodeiter(first, last, 0); + end = p.second-first; + return p.first; } +} // namespace -SharedHandle<ValueBase> decode(const std::string& s) +SharedHandle<ValueBase> decode +(std::string::const_iterator first, + std::string::const_iterator last) { size_t end; - return decode(s, end); + return decodegen(first, last, end); } -SharedHandle<ValueBase> decode(const std::string& s, size_t& end) +SharedHandle<ValueBase> decode +(std::string::const_iterator first, + std::string::const_iterator last, + size_t& end) { - if(s.empty()) { - return SharedHandle<ValueBase>(); - } - std::istringstream ss(s); - - SharedHandle<ValueBase> vlb = decodeiter(ss, 0); - end = ss.tellg(); - return vlb; + return decodegen(first, last, end); } -SharedHandle<ValueBase> decode(const unsigned char* data, size_t length) +SharedHandle<ValueBase> decode +(const unsigned char* first, + const unsigned char* last) { - return decode(std::string(&data[0], &data[length])); + size_t end; + return decodegen(first, last, end); } -SharedHandle<ValueBase> decode(const unsigned char* data, size_t length, size_t& end) +SharedHandle<ValueBase> decode +(const unsigned char* first, + const unsigned char* last, + size_t& end) { - return decode(std::string(&data[0], &data[length]), end); + return decodegen(first, last, end); } SharedHandle<ValueBase> decodeFromFile(const std::string& filename) @@ -225,7 +252,9 @@ SharedHandle<ValueBase> decodeFromFile(const std::string& filename) std::stringstream ss; fp.transfer(ss); fp.close(); - return decode(ss); + const std::string s = ss.str(); + size_t end; + return decodegen(s.begin(), s.end(), end); } else { throw DL_ABORT_EX2 (fmt("Bencode decoding failed: Cannot open file '%s'.", diff --git a/src/bencode2.h b/src/bencode2.h index 7f4e226f..bfc95de6 100644 --- a/src/bencode2.h +++ b/src/bencode2.h @@ -48,19 +48,26 @@ namespace bencode2 { const size_t MAX_STRUCTURE_DEPTH = 100; -SharedHandle<ValueBase> decode(std::istream& in); - -// Decode the data in s. -SharedHandle<ValueBase> decode(const std::string& s); +// Decode the data in [first, last). +SharedHandle<ValueBase> decode +(std::string::const_iterator first, + std::string::const_iterator last); -// Decode the data in s. After decode is done successfully, return the -// bencoded string length in end. -SharedHandle<ValueBase> decode(const std::string& s, size_t& end); +// Decode the data in [first, last). After decode is done +// successfully, return the bencoded string length in end. +SharedHandle<ValueBase> decode +(std::string::const_iterator first, + std::string::const_iterator last, + size_t& end); -SharedHandle<ValueBase> decode(const unsigned char* data, size_t length); +SharedHandle<ValueBase> decode +(const unsigned char* first, + const unsigned char* last); SharedHandle<ValueBase> decode -(const unsigned char* data, size_t length, size_t& end); +(const unsigned char* first, + const unsigned char* last, + size_t& end); SharedHandle<ValueBase> decodeFromFile(const std::string& filename); diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 0346d96b..27f82443 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -544,7 +544,7 @@ void loadFromMemory(const unsigned char* content, const std::string& overrideName) { processRootDictionary(ctx, - bencode2::decode(content, length), + bencode2::decode(content, content+length), option, defaultName, overrideName, @@ -560,7 +560,7 @@ void loadFromMemory(const unsigned char* content, const std::string& overrideName) { processRootDictionary(ctx, - bencode2::decode(content, length), + bencode2::decode(content, content+length), option, defaultName, overrideName, @@ -575,7 +575,7 @@ void loadFromMemory(const std::string& context, { processRootDictionary (ctx, - bencode2::decode(context), + bencode2::decode(context.begin(), context.end()), option, defaultName, overrideName, std::vector<std::string>()); @@ -590,7 +590,7 @@ void loadFromMemory(const std::string& context, { processRootDictionary (ctx, - bencode2::decode(context), + bencode2::decode(context.begin(), context.end()), option, defaultName, overrideName, uris); @@ -112,7 +112,8 @@ namespace util { template<typename InputIterator> void divide -(std::pair<Scip, Scip>& hp, +(std::pair<std::pair<InputIterator, InputIterator>, + std::pair<InputIterator, InputIterator> >& hp, InputIterator first, InputIterator last, char delim) @@ -248,7 +249,7 @@ bool parseIntNoThrow (int32_t& result, InputIterator first, InputIterator last, int base = 10) { // Without strip, strtol(" -1 ",..) emits error. - Scip p = util::stripIter(first, last); + std::pair<InputIterator, InputIterator> p = util::stripIter(first, last); if(p.first == p.second) { return false; } @@ -277,7 +278,7 @@ bool parseUIntNoThrow (uint32_t& result, InputIterator first, InputIterator last, int base = 10) { // Without strip, strtol(" -1 ",..) emits error. - Scip p = util::stripIter(first, last); + std::pair<InputIterator, InputIterator> p = util::stripIter(first, last); if(p.first == p.second) { return false; } @@ -309,7 +310,7 @@ bool parseLLIntNoThrow (int64_t& result, InputIterator first, InputIterator last, int base = 10) { // Without strip, strtol(" -1 ",..) emits error. - Scip p = util::stripIter(first, last); + std::pair<InputIterator, InputIterator> p = util::stripIter(first, last); if(p.first == p.second) { return false; } @@ -335,7 +336,7 @@ bool parseLLIntNoThrow template<typename InputIterator> int64_t parseLLInt(InputIterator first, InputIterator last, int base = 10) { - Scip p = util::stripIter(first, last); + std::pair<InputIterator, InputIterator> p = util::stripIter(first, last); if(p.first == p.second) { throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, "empty string")); @@ -373,7 +374,7 @@ int32_t parseInt(InputIterator first, InputIterator last, int base = 10) template<typename InputIterator> uint64_t parseULLInt(InputIterator first, InputIterator last, int base = 10) { - Scip p = util::stripIter(first, last); + std::pair<InputIterator, InputIterator> p = util::stripIter(first, last); if(p.first == p.second) { throw DL_ABORT_EX(fmt(MSG_STRING_INTEGER_CONVERSION_FAILURE, "empty string")); |
