Browse Source

Rewritten bencode2::decode functions

Tatsuhiro Tsujikawa 14 years ago
parent
commit
d1d4903665

+ 1 - 1
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));

+ 1 - 1
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);

+ 2 - 1
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");

+ 1 - 1
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);
     }

+ 1 - 1
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

+ 4 - 3
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());
 }
 

+ 1 - 1
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;

+ 1 - 1
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) {

+ 1 - 1
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"));

+ 109 - 80
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'.",

+ 16 - 9
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);
 

+ 4 - 4
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);

+ 7 - 6
src/util.h

@@ -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"));

+ 16 - 8
test/AnnounceListTest.cc

@@ -64,7 +64,8 @@ std::vector<std::vector<std::string> > toVector
 
 void AnnounceListTest::testSingleElementList() {
   std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
@@ -110,7 +111,8 @@ void AnnounceListTest::testSingleElementList() {
 
 void AnnounceListTest::testMultiElementList() {
   std::string peersString = "ll8:tracker18:tracker28:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1, tracker2, tracker3 ] ]
@@ -143,7 +145,8 @@ void AnnounceListTest::testMultiElementList() {
 
 void AnnounceListTest::testSingleAndMulti() {
   std::string peersString = "ll8:tracker18:tracker2el8:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1, tracker2 ], [ tracker3 ] ]
@@ -169,14 +172,16 @@ void AnnounceListTest::testSingleAndMulti() {
 
 void AnnounceListTest::testNoGroup() {
   std::string peersString = "llee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
   AnnounceList announceList(toVector(downcast<List>(announcesList)));
   CPPUNIT_ASSERT(announceList.countTier() == 0);
 }
 
 void AnnounceListTest::testNextEventIfAfterStarted() {
   std::string peersString = "ll8:tracker1ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1 ] ]
@@ -196,7 +201,8 @@ void AnnounceListTest::testNextEventIfAfterStarted() {
 
 void AnnounceListTest::testEvent() {
   std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
@@ -220,7 +226,8 @@ void AnnounceListTest::testEvent() {
 
 void AnnounceListTest::testCountStoppedAllowedTier() {
   std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]
@@ -247,7 +254,8 @@ void AnnounceListTest::testCountStoppedAllowedTier() {
 
 void AnnounceListTest::testCountCompletedAllowedTier() {
   std::string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
-  SharedHandle<ValueBase> announcesList = bencode2::decode(peersString);
+  SharedHandle<ValueBase> announcesList =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   // ANNOUNCE_LIST
   // [ [ tracker1 ], [ tracker2 ], [ tracker3 ] ]

+ 32 - 18
test/Bencode2Test.cc

@@ -27,8 +27,8 @@ void Bencode2Test::testDecode()
 {
   {
     // string, integer and list in dict
-    SharedHandle<ValueBase> r =
-      bencode2::decode("d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee");
+    std::string src = "d4:name5:aria24:sizei12345678900e5:filesl3:bin3:docee";
+    SharedHandle<ValueBase> r = bencode2::decode(src.begin(), src.end());
     const Dict* dict = downcast<Dict>(r);
     CPPUNIT_ASSERT(dict);
     CPPUNIT_ASSERT_EQUAL(std::string("aria2"),
@@ -45,7 +45,8 @@ void Bencode2Test::testDecode()
   }
   {
     // dict in list
-    SharedHandle<ValueBase> r = bencode2::decode("ld1:ki123eee");
+    std::string src = "ld1:ki123eee";
+    SharedHandle<ValueBase> r = bencode2::decode(src.begin(), src.end());
     const List* list = downcast<List>(r);
     CPPUNIT_ASSERT(list);
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), list->size());
@@ -56,38 +57,44 @@ void Bencode2Test::testDecode()
   }
   {
     // empty key is allowed
-    SharedHandle<ValueBase> s = bencode2::decode("d0:1:ve");
+    std::string src = "d0:1:ve";
+    SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
   }
   {
     // empty string
-    SharedHandle<ValueBase> s = bencode2::decode("0:");
+    std::string src = "0:";
+    SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
     CPPUNIT_ASSERT_EQUAL(std::string(""), downcast<String>(s)->s());
   }
   {
     // empty dict
-    SharedHandle<ValueBase> d = bencode2::decode("de");
+    std::string src = "de";
+    SharedHandle<ValueBase> d = bencode2::decode(src.begin(), src.end());
     CPPUNIT_ASSERT(downcast<Dict>(d)->empty());
   }
   {
     // empty list
-    SharedHandle<ValueBase> l = bencode2::decode("le");
+    std::string src = "le";
+    SharedHandle<ValueBase> l = bencode2::decode(src.begin(), src.end());
     CPPUNIT_ASSERT(downcast<List>(l)->empty());
   }
   {
     // integer, without ending 'e'
+    std::string src = "i3";
     try {
-      bencode2::decode("i3");
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
-                                       " Delimiter 'e' not found."),
+                                       " Integer expected but none found"),
                            std::string(e.what()));
     }    
   }
   {
     // dict, without ending 'e'
+    std::string src = "d";
     try {
-      bencode2::decode("d");
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
@@ -99,7 +106,8 @@ void Bencode2Test::testDecode()
   {
     // list, without ending 'e'
     try {
-      bencode2::decode("l");
+      std::string src = "l";
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
@@ -111,7 +119,8 @@ void Bencode2Test::testDecode()
   {
     // string, less than the specified length.
     try {
-      bencode2::decode("3:ab");
+      std::string src = "3:ab";
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
@@ -123,7 +132,8 @@ void Bencode2Test::testDecode()
   {
     // string, but length is invalid
     try {
-      bencode2::decode("x:abc");
+      std::string src = "x:abc";
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
@@ -134,8 +144,9 @@ void Bencode2Test::testDecode()
   }
   {
     // string with minus length
+    std::string src = "-1:a";
     try {
-      bencode2::decode("-1:a");
+      bencode2::decode(src.begin(), src.end());
       CPPUNIT_FAIL("exception must be thrown.");
     } catch(RecoverableException& e) {
       CPPUNIT_ASSERT_EQUAL(std::string("Bencode decoding failed:"
@@ -146,17 +157,20 @@ void Bencode2Test::testDecode()
   }
   {
     // empty encoded data
-    CPPUNIT_ASSERT(!bencode2::decode(""));
+    std::string src = "";
+    CPPUNIT_ASSERT(!bencode2::decode(src.begin(), src.end()));
   }
   {
     // ignore trailing garbage at the end of the input.
-    SharedHandle<ValueBase> s = bencode2::decode("5:aria2trail");
+    std::string src = "5:aria2trail";
+    SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end());
     CPPUNIT_ASSERT_EQUAL(std::string("aria2"), downcast<String>(s)->s());
   }
   {
     // Get trailing garbage position
+    std::string src = "5:aria2trail";
     size_t end;
-    SharedHandle<ValueBase> s = bencode2::decode("5:aria2trail", end);
+    SharedHandle<ValueBase> s = bencode2::decode(src.begin(), src.end(), end);
     CPPUNIT_ASSERT_EQUAL(std::string("aria2"), downcast<String>(s)->s());
     CPPUNIT_ASSERT_EQUAL((size_t)7, end);
   }
@@ -173,7 +187,7 @@ void Bencode2Test::testDecode_overflow()
     s += "e";
   }
   try {
-    bencode2::decode(s);
+    bencode2::decode(s.begin(), s.end());
     CPPUNIT_FAIL("exception must be thrown.");
   } catch(RecoverableException& e) {
     // success

+ 9 - 5
test/BittorrentHelperTest.cc

@@ -746,7 +746,8 @@ void BittorrentHelperTest::testMetadata() {
   SharedHandle<DownloadContext> dctx(new DownloadContext());
   load(A2_TEST_DIR"/test.torrent", dctx, option_);
   std::string torrentData = readFile(A2_TEST_DIR"/test.torrent");
-  SharedHandle<ValueBase> tr = bencode2::decode(torrentData);
+  SharedHandle<ValueBase> tr =
+    bencode2::decode(torrentData.begin(), torrentData.end());
   SharedHandle<ValueBase> infoDic = downcast<Dict>(tr)->get("info");
   std::string metadata = bencode2::encode(infoDic);
   SharedHandle<TorrentAttribute> attrs = getTorrentAttrs(dctx);
@@ -830,7 +831,8 @@ void BittorrentHelperTest::testExtractPeerFromString()
   std::string hextext = "100210354527354678541237324732171ae1";
   hextext += "20010db8bd0501d2288a1fc0000110ee1ae2";
   std::string peersstr = "36:"+util::fromHex(hextext);
-  SharedHandle<ValueBase> str = bencode2::decode(peersstr);
+  SharedHandle<ValueBase> str =
+    bencode2::decode(peersstr.begin(), peersstr.end());
   std::deque<SharedHandle<Peer> > peers;
   extractPeer(str, AF_INET6, std::back_inserter(peers));
   CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
@@ -844,7 +846,7 @@ void BittorrentHelperTest::testExtractPeerFromString()
   hextext = "c0a800011ae1";
   hextext += "c0a800021ae2";
   peersstr = "12:"+util::fromHex(hextext);
-  str = bencode2::decode(peersstr);
+  str = bencode2::decode(peersstr.begin(), peersstr.end());
   peers.clear();
   extractPeer(str, AF_INET, std::back_inserter(peers));
   CPPUNIT_ASSERT_EQUAL((size_t)2, peers.size());
@@ -860,7 +862,8 @@ void BittorrentHelperTest::testExtractPeerFromList()
     "d5:peersld2:ip11:192.168.0.17:peer id20:aria2-00000000000000"
     "4:porti2006eeee";
 
-  SharedHandle<ValueBase> dict = bencode2::decode(peersString);
+  SharedHandle<ValueBase> dict =
+    bencode2::decode(peersString.begin(), peersString.end());
   
   std::deque<SharedHandle<Peer> > peers;
   extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET, std::back_inserter(peers));
@@ -877,7 +880,8 @@ void BittorrentHelperTest::testExtract2PeersFromList()
     "4:porti65535eed2:ip11:192.168.0.27:peer id20:aria2-00000000000000"
     "4:porti2007eeee";
 
-  SharedHandle<ValueBase> dict = bencode2::decode(peersString);
+  SharedHandle<ValueBase> dict =
+    bencode2::decode(peersString.begin(), peersString.end());
 
   std::deque<SharedHandle<Peer> > peers;
   extractPeer(downcast<Dict>(dict)->get("peers"), AF_INET, std::back_inserter(peers));

+ 1 - 1
test/UtilTest.cc

@@ -268,7 +268,7 @@ void UtilTest::testLstripIter_char()
 }
 
 void UtilTest::testDivide() {
-  std::pair<Scip, Scip> p1;
+  std::pair<Sip, Sip> p1;
   std::string s = "name=value";
   util::divide(p1, s.begin(), s.end(), '=');
   CPPUNIT_ASSERT_EQUAL(std::string("name"),