Selaa lähdekoodia

util::divide now takes iterators as arguments.

Tatsuhiro Tsujikawa 14 vuotta sitten
vanhempi
commit
6267676e8b

+ 16 - 21
src/ExpatMetalinkProcessor.cc

@@ -35,6 +35,7 @@
 #include "ExpatMetalinkProcessor.h"
 
 #include <cstdio>
+#include <cstring>
 
 #include "DefaultDiskWriter.h"
 #include "MetalinkParserStateMachine.h"
@@ -63,17 +64,18 @@ public:
 } // namespace
 
 namespace {
+template<typename InputIterator>
 void splitNsName
 (std::string& localname, std::string& prefix, std::string& nsUri,
- const std::string& nsName)
+ InputIterator first, InputIterator last)
 {
-  std::pair<std::string, std::string> nsNamePair;
-  util::divide(nsNamePair, nsName, '\t');
-  if(nsNamePair.second.empty()) {
-    localname = nsNamePair.first;
+  std::pair<Scip, Scip> nsNamePair;
+  util::divide(nsNamePair, first, last, '\t');
+  if(nsNamePair.second.first == nsNamePair.second.second) {
+    localname.assign(nsNamePair.first.first, nsNamePair.first.second);
   } else {
-    nsUri = nsNamePair.first;
-    localname = nsNamePair.second;
+    nsUri.assign(nsNamePair.first.first, nsNamePair.first.second);
+    localname.assign(nsNamePair.second.first, nsNamePair.second.second);
   }
 }
 } // namespace
@@ -87,29 +89,22 @@ void mlStartElement(void* userData, const char* nsName, const char** attrs)
   if(attrs) {
     const char** p = attrs;
     while(*p != 0) {
-      std::string attrNsName = *p++;
+      const char* attrNsName = *p++;
       if(*p == 0) {
         break;
       }
-      std::string value = *p++;
-      std::pair<std::string, std::string> nsNamePair;
-      util::divide(nsNamePair, attrNsName, '\t');
       XmlAttr xa;
-      if(nsNamePair.second.empty()) {
-        xa.localname = nsNamePair.first;
-      } else {
-        xa.nsUri = nsNamePair.first;
-        xa.localname = nsNamePair.second;
-      }
-      xa.value = value;
+      splitNsName(xa.localname, xa.prefix, xa.nsUri,
+                  attrNsName, attrNsName+strlen(attrNsName));
+      const char* value = *p++;
+      xa.value.assign(value, value+strlen(value));
       xmlAttrs.push_back(xa);
     }
   }
   std::string localname;
   std::string prefix;
   std::string nsUri;
-  splitNsName(localname, prefix, nsUri, nsName);
-  
+  splitNsName(localname, prefix, nsUri, nsName, nsName+strlen(nsName));
   sd->stm_->beginElement(localname, prefix, nsUri, xmlAttrs);
   if(sd->stm_->needsCharactersBuffering()) {
     sd->charactersStack_.push_front(A2STR::NIL);
@@ -123,7 +118,7 @@ void mlEndElement(void* userData, const char* nsName)
   std::string localname;
   std::string prefix;
   std::string nsUri;
-  splitNsName(localname, prefix, nsUri, nsName);
+  splitNsName(localname, prefix, nsUri, nsName, nsName+strlen(nsName));
 
   SessionData* sd = reinterpret_cast<SessionData*>(userData);
   std::string characters;

+ 3 - 3
src/FtpConnection.cc

@@ -435,9 +435,9 @@ unsigned int FtpConnection::receiveSizeResponse(uint64_t& size)
   std::pair<unsigned int, std::string> response;
   if(bulkReceiveResponse(response)) {
     if(response.first == 213) {
-      std::pair<std::string, std::string> rp;
-      util::divide(rp, response.second, ' ');
-      size = util::parseULLInt(rp.second.begin(), rp.second.end());
+      std::pair<Scip, Scip> rp;
+      util::divide(rp, response.second.begin(), response.second.end(), ' ');
+      size = util::parseULLInt(rp.second.first, rp.second.second);
     }
     return response.first;
   } else {

+ 4 - 3
src/HttpResponse.cc

@@ -249,9 +249,10 @@ std::string HttpResponse::getContentType() const
   if(!httpHeader_) {
     return A2STR::NIL;
   } else {
-    std::pair<std::string, std::string> p;
-    util::divide(p, httpHeader_->getFirst(HttpHeader::CONTENT_TYPE), ';');
-    return p.first;
+    const std::string& ctype = httpHeader_->getFirst(HttpHeader::CONTENT_TYPE);
+    std::string::const_iterator i = std::find(ctype.begin(), ctype.end(), ';');
+    Scip p = util::stripIter(ctype.begin(), i);
+    return std::string(p.first, p.second);
   }
 }
 

+ 15 - 8
src/HttpServer.cc

@@ -203,19 +203,26 @@ bool HttpServer::authenticate()
     return true;
   }
 
-  std::string authHeader = lastRequestHeader_->getFirst("Authorization");
+  const std::string& authHeader = lastRequestHeader_->getFirst("Authorization");
   if(authHeader.empty()) {
     return false;
   }
-  std::pair<std::string, std::string> p;
-  util::divide(p, authHeader, ' ');
-  if(p.first != "Basic") {
+  std::pair<Scip, Scip> p;
+  util::divide(p, authHeader.begin(), authHeader.end(), ' ');
+  const char authMethod[] = "Basic";
+  if(!std::distance(p.first.first, p.first.second) == sizeof(authMethod) ||
+     !std::equal(p.first.first, p.first.second, &authMethod[0])) {
     return false;
   }
-  std::string userpass = Base64::decode(p.second);
-  std::pair<std::string, std::string> userpassPair;
-  util::divide(userpassPair, userpass, ':');
-  return username_ == userpassPair.first && password_ == userpassPair.second;
+  std::string userpass = Base64::decode(std::string(p.second.first,
+                                                    p.second.second));
+  util::divide(p, userpass.begin(), userpass.end(), ':');
+  return username_.size() ==
+    static_cast<size_t>(std::distance(p.first.first, p.first.second)) &&
+    std::equal(username_.begin(), username_.end(), p.first.first) &&
+    password_.size() ==
+    static_cast<size_t>(std::distance(p.second.first, p.second.second)) &&
+    std::equal(password_.begin(), password_.end(), p.second.first);
 }
 
 void HttpServer::setUsernamePassword

+ 7 - 5
src/OptionHandlerImpl.cc

@@ -365,11 +365,13 @@ ChecksumOptionHandler::~ChecksumOptionHandler() {}
 
 void ChecksumOptionHandler::parseArg(Option& option, const std::string& optarg)
 {
-  std::pair<std::string, std::string> p;
-  util::divide(p, optarg, '=');
-  util::lowercase(p.first);
-  util::lowercase(p.second);
-  if(!MessageDigest::isValidHash(p.first, p.second)) {
+  std::pair<Scip, Scip> p;
+  util::divide(p, optarg.begin(), optarg.end(), '=');
+  std::string hashType(p.first.first, p.first.second);
+  std::string hexDigest(p.second.first, p.second.second);
+  util::lowercase(hashType);
+  util::lowercase(hexDigest);
+  if(!MessageDigest::isValidHash(hashType, hexDigest)) {
     throw DL_ABORT_EX(_("Unrecognized checksum"));
   }
   option.put(pref_, optarg);

+ 6 - 5
src/OptionParser.cc

@@ -184,14 +184,15 @@ void OptionParser::parse(Option& option, std::istream& is) const
     if(util::startsWith(line, A2STR::SHARP_C)) {
       continue;
     }
-    std::pair<std::string, std::string> nv;
-    util::divide(nv, line, '=');
-    if(nv.first.empty()) {
+    std::pair<Scip, Scip> nv;
+    util::divide(nv, line.begin(), line.end(), '=');
+    if(nv.first.first == nv.first.second) {
       continue;
     }
-    const SharedHandle<OptionHandler>& handler = find(option::k2p(nv.first));
+    const SharedHandle<OptionHandler>& handler =
+      find(option::k2p(std::string(nv.first.first, nv.first.second)));
     if(handler) {
-      handler->parse(option, nv.second);
+      handler->parse(option, std::string(nv.second.first, nv.second.second));
     }
   }
 }

+ 18 - 15
src/ParameterizedStringParser.cc

@@ -124,26 +124,29 @@ ParameterizedStringParser::createLoop(const std::string& src, int& offset)
     }
     loopStr.erase(colonIndex);
   }
-  std::pair<std::string, std::string> range;
-  util::divide(range, loopStr, '-');
-  if(range.first.empty() || range.second.empty()) {
+  std::pair<Scip, Scip> range;
+  util::divide(range, loopStr.begin(), loopStr.end(), '-');
+  if(range.first.first == range.first.second ||
+     range.second.first == range.second.second) {
     throw DL_ABORT_EX("Loop range missing.");
   }
   SharedHandle<NumberDecorator> nd;
   unsigned int start;
   unsigned int end;
-  if(util::isNumber(range.first) && util::isNumber(range.second)) {
-    nd.reset(new FixedWidthNumberDecorator(range.first.size()));
-    start = util::parseUInt(range.first.begin(), range.first.end());
-    end = util::parseUInt(range.second.begin(), range.second.end());
-  } else if(util::isLowercase(range.first) && util::isLowercase(range.second)) {
-    nd.reset(new AlphaNumberDecorator(range.first.size()));
-    start = util::alphaToNum(range.first);
-    end = util::alphaToNum(range.second);
-  } else if(util::isUppercase(range.first) && util::isUppercase(range.second)) {
-    nd.reset(new AlphaNumberDecorator(range.first.size(), true));
-    start = util::alphaToNum(range.first);
-    end = util::alphaToNum(range.second);
+  std::string rstart(range.first.first, range.first.second);
+  std::string rend(range.second.first, range.second.second);
+  if(util::isNumber(rstart) && util::isNumber(rend)) {
+    nd.reset(new FixedWidthNumberDecorator(rstart.size()));
+    start = util::parseUInt(rstart.begin(), rstart.end());
+    end = util::parseUInt(rend.begin(), rend.end());
+  } else if(util::isLowercase(rstart) && util::isLowercase(rend)) {
+    nd.reset(new AlphaNumberDecorator(rstart.size()));
+    start = util::alphaToNum(rstart);
+    end = util::alphaToNum(rend);
+  } else if(util::isUppercase(rstart) && util::isUppercase(rend)) {
+    nd.reset(new AlphaNumberDecorator(rstart.size(), true));
+    start = util::alphaToNum(rstart);
+    end = util::alphaToNum(rend);
   } else {
     throw DL_ABORT_EX("Invalid loop range.");
   }

+ 8 - 5
src/RpcMethodImpl.cc

@@ -1126,11 +1126,14 @@ void changeOption
   const SharedHandle<Option>& grOption = group->getOption();
   grOption->merge(option);
   if(option.defined(PREF_CHECKSUM)) {
-    std::pair<std::string, std::string> p;
-    util::divide(p, grOption->get(PREF_CHECKSUM), '=');
-    util::lowercase(p.first);
-    util::lowercase(p.second);
-    dctx->setDigest(p.first, util::fromHex(p.second));
+    const std::string& checksum = grOption->get(PREF_CHECKSUM);
+    std::pair<Scip, Scip> p;
+    util::divide(p, checksum.begin(), checksum.end(), '=');
+    std::string hashType(p.first.first, p.first.second);
+    std::string hexDigest(p.second.first, p.second.second);
+    util::lowercase(hashType);
+    util::lowercase(hexDigest);
+    dctx->setDigest(hashType, util::fromHex(hexDigest));
   }
   if(option.defined(PREF_SELECT_FILE)) {
     SegList<int> sgl;

+ 4 - 5
src/ServerStatMan.cc

@@ -160,11 +160,10 @@ bool ServerStatMan::load(const std::string& filename)
     std::map<std::string, std::string> m;
     for(std::vector<std::string>::const_iterator i = items.begin(),
           eoi = items.end(); i != eoi; ++i) {
-      std::pair<std::string, std::string> p;
-      util::divide(p, *i, '=');
-      p.first = util::strip(p.first);
-      p.second = util::strip(p.second);
-      m[p.first] = p.second;
+      std::pair<Scip, Scip> p;
+      util::divide(p, (*i).begin(), (*i).end(), '=');
+      m[std::string(p.first.first, p.first.second)] =
+        std::string(p.second.first, p.second.second);
     }
     if(m[S_HOST].empty() || m[S_PROTOCOL].empty()) {
       continue;

+ 7 - 5
src/download_helper.cc

@@ -129,11 +129,13 @@ SharedHandle<RequestGroup> createRequestGroup
 #ifdef ENABLE_MESSAGE_DIGEST
   const std::string& checksum = option->get(PREF_CHECKSUM);
   if(!checksum.empty()) {
-    std::pair<std::string, std::string> p;
-    util::divide(p, checksum, '=');
-    util::lowercase(p.first);
-    util::lowercase(p.second);
-    dctx->setDigest(p.first, util::fromHex(p.second));
+    std::pair<Scip, Scip> p;
+    util::divide(p, checksum.begin(), checksum.end(), '=');
+    std::string hashType(p.first.first, p.first.second);
+    std::string hexDigest(p.second.first, p.second.second);
+    util::lowercase(hashType);
+    util::lowercase(hexDigest);
+    dctx->setDigest(hashType, hexDigest);
   }
 #endif // ENABLE_MESSAGE_DIGEST
   rg->setDownloadContext(dctx);

+ 13 - 33
src/util.cc

@@ -191,24 +191,6 @@ std::string strip(const std::string& str, const std::string& chars)
   return std::string(p.first, p.second);
 }
 
-void divide
-(std::pair<std::string, std::string>& hp, const std::string& src, char delim)
-{
-  std::string::const_iterator first = src.begin();
-  std::string::const_iterator last = src.end();
-  std::string::const_iterator dpos = std::find(first, last, delim);
-  if(dpos == last) {
-    hp.first = strip(src);
-    hp.second = A2STR::NIL;
-  } else {
-    std::pair<std::string::const_iterator,
-              std::string::const_iterator> p = stripIter(first, dpos);
-    hp.first.assign(p.first, p.second);
-    p = stripIter(dpos+1, last);
-    hp.second.assign(p.first, p.second);
-  }
-}
-
 std::string itos(int64_t value, bool comma)
 {
   bool flag = false;
@@ -820,11 +802,9 @@ std::string getContentDispositionFilename(const std::string& header)
       if(markeritr == param.end() || *markeritr != '=') {
         continue;
       }
-      std::pair<std::string, std::string> paramPair;
-      divide(paramPair, param, '=');
-      std::string value = paramPair.second;
+      std::string value(markeritr+1, param.end());
       std::vector<std::string> extValues;
-      split(value, std::back_inserter(extValues), "'", false, true);
+      split(value, std::back_inserter(extValues), "'", true, true);
       if(extValues.size() != 3) {
         continue;
       }
@@ -877,17 +857,17 @@ std::string getContentDispositionFilename(const std::string& header)
       }
     } else {
       for(; markeritr != param.end() && *markeritr == ' '; ++markeritr);
-      if(markeritr == param.end() || *markeritr != '=') {
+      if(markeritr == param.end() || markeritr+1 == param.end() ||
+         *markeritr != '=') {
         continue;
       }
-      std::pair<std::string, std::string> paramPair;
-      divide(paramPair, param, '=');
-      std::string value = paramPair.second;
-      if(value.empty()) {
+      Scip p = stripIter(markeritr+1, param.end());
+      if(p.first == p.second) {
         continue;
       }
+      std::string value(p.first, p.second);
       std::string::iterator filenameLast;
-      if(*value.begin() == '\'' || *value.begin() == '"') {
+      if(value[0] == '\'' || value[0] == '"') {
         char qc = *value.begin();
         for(filenameLast = value.begin()+1;
             filenameLast != value.end() && *filenameLast != qc;
@@ -1248,14 +1228,14 @@ std::string htmlEscape(const std::string& src)
 std::pair<size_t, std::string>
 parseIndexPath(const std::string& line)
 {
-  std::pair<std::string, std::string> p;
-  divide(p, line, '=');
-  size_t index = parseUInt(p.first.begin(), p.first.end());
-  if(p.second.empty()) {
+  std::pair<Scip, Scip> p;
+  divide(p, line.begin(), line.end(), '=');
+  size_t index = parseUInt(p.first.first, p.first.second);
+  if(p.second.first == p.second.second) {
     throw DL_ABORT_EX(fmt("Path with index=%u is empty.",
                           static_cast<unsigned int>(index)));
   }
-  return std::make_pair(index, p.second);
+  return std::make_pair(index, std::string(p.second.first, p.second.second));
 }
 
 std::vector<std::pair<size_t, std::string> > createIndexPaths(std::istream& i)

+ 15 - 1
src/util.h

@@ -110,8 +110,22 @@ std::string nativeToUtf8(const std::string& src);
 
 namespace util {
 
+template<typename InputIterator>
 void divide
-(std::pair<std::string, std::string>& hp, const std::string& src, char delim);
+(std::pair<Scip, Scip>& hp,
+ InputIterator first,
+ InputIterator last,
+ char delim)
+{
+  InputIterator dpos = std::find(first, last, delim);
+  if(dpos == last) {
+    hp.first = stripIter(first, last);
+    hp.second.first = hp.second.second;
+  } else {
+    hp.first = stripIter(first, dpos);
+    hp.second = stripIter(dpos+1, last);
+  }
+}
 
 template<typename T>
 std::string uitos(T value, bool comma = false)

+ 35 - 16
test/UtilTest.cc

@@ -212,22 +212,37 @@ void UtilTest::testStripIter()
 }
 
 void UtilTest::testDivide() {
-  std::pair<std::string, std::string> p1;
-  util::divide(p1, "name=value", '=');
-  CPPUNIT_ASSERT_EQUAL(std::string("name"), p1.first);
-  CPPUNIT_ASSERT_EQUAL(std::string("value"), p1.second);
-  util::divide(p1, " name = value ", '=');
-  CPPUNIT_ASSERT_EQUAL(std::string("name"), p1.first);
-  CPPUNIT_ASSERT_EQUAL(std::string("value"), p1.second);
-  util::divide(p1, "=value", '=');
-  CPPUNIT_ASSERT_EQUAL(std::string(""), p1.first);
-  CPPUNIT_ASSERT_EQUAL(std::string("value"), p1.second);
-  util::divide(p1, "name=", '=');
-  CPPUNIT_ASSERT_EQUAL(std::string("name"), p1.first);
-  CPPUNIT_ASSERT_EQUAL(std::string(""), p1.second);
-  util::divide(p1, "name", '=');
-  CPPUNIT_ASSERT_EQUAL(std::string("name"), p1.first);
-  CPPUNIT_ASSERT_EQUAL(std::string(""), p1.second);
+  std::pair<Scip, Scip> p1;
+  std::string s = "name=value";
+  util::divide(p1, s.begin(), s.end(), '=');
+  CPPUNIT_ASSERT_EQUAL(std::string("name"),
+                       std::string(p1.first.first, p1.first.second));
+  CPPUNIT_ASSERT_EQUAL(std::string("value"),
+                       std::string(p1.second.first, p1.second.second));
+  s = " name = value ";
+  util::divide(p1, s.begin(), s.end(), '=');
+  CPPUNIT_ASSERT_EQUAL(std::string("name"),
+                       std::string(p1.first.first, p1.first.second));
+  CPPUNIT_ASSERT_EQUAL(std::string("value"),
+                       std::string(p1.second.first, p1.second.second));
+  s = "=value";
+  util::divide(p1, s.begin(), s.end(), '=');
+  CPPUNIT_ASSERT_EQUAL(std::string(""),
+                       std::string(p1.first.first, p1.first.second));
+  CPPUNIT_ASSERT_EQUAL(std::string("value"),
+                       std::string(p1.second.first, p1.second.second));
+  s = "name=";
+  util::divide(p1, s.begin(), s.end(), '=');
+  CPPUNIT_ASSERT_EQUAL(std::string("name"),
+                       std::string(p1.first.first, p1.first.second));
+  CPPUNIT_ASSERT_EQUAL(std::string(""),
+                       std::string(p1.second.first, p1.second.second));
+  s = "name";
+  util::divide(p1, s.begin(), s.end(), '=');
+  CPPUNIT_ASSERT_EQUAL(std::string("name"),
+                       std::string(p1.first.first, p1.first.second));
+  CPPUNIT_ASSERT_EQUAL(std::string(""),
+                       std::string(p1.second.first, p1.second.second));
 }
 
 void UtilTest::testSplit() {
@@ -407,6 +422,10 @@ void UtilTest::testGetContentDispositionFilename() {
   std::string h3 = "attachment; filename=\"";
   CPPUNIT_ASSERT_EQUAL(std::string(""), util::getContentDispositionFilename(h3));
 
+  std::string h3_2 = "attachment; filename= \" aria2.tar.bz2 \"";
+  CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2"),
+                       util::getContentDispositionFilename(h3_2));
+
   std::string h4 = "attachment;";
   CPPUNIT_ASSERT_EQUAL(std::string(""), util::getContentDispositionFilename(h4));