فهرست منبع

Added BufferedFile::getLine() to make reading one line more flexible.

Fixes bug#3495336
Tatsuhiro Tsujikawa 13 سال پیش
والد
کامیت
037f1512db
6فایلهای تغییر یافته به همراه86 افزوده شده و 50 حذف شده
  1. 22 0
      src/BufferedFile.cc
  2. 4 2
      src/BufferedFile.h
  3. 19 10
      src/Netrc.cc
  4. 14 8
      src/NsCookieParser.cc
  5. 7 6
      src/ServerStatMan.cc
  6. 20 24
      src/UriListParser.cc

+ 22 - 0
src/BufferedFile.cc

@@ -99,6 +99,28 @@ char* BufferedFile::getsn(char* s, int size)
   return ptr;
 }
 
+std::string BufferedFile::getLine()
+{
+  std::string res;
+  if(eof()) {
+    return res;
+  }
+  char buf[4096];
+  while(gets(buf, sizeof(buf))) {
+    size_t len = strlen(buf);
+    bool lineBreak = false;
+    if(buf[len-1] == '\n') {
+      --len;
+      lineBreak = true;
+    }
+    res.append(buf, len);
+    if(lineBreak) {
+      break;
+    }
+  }
+  return res;
+}
+
 int BufferedFile::close()
 {
   if(open_) {

+ 4 - 2
src/BufferedFile.h

@@ -52,8 +52,8 @@ public:
   BufferedFile(const std::string& filename, const std::string& mode);
   BufferedFile(FILE* fp);
   virtual ~BufferedFile();
-  // Returns true if file is opened and both ferror and feof returns
-  // 0. Otherwise returns false.
+  // Returns true if file is opened and ferror returns 0. Otherwise
+  // returns false.
   operator unspecified_bool_type() const;
   // wrapper for fread. Using 1 for 2nd argument of fread.
   size_t read(void* ptr, size_t count);
@@ -64,6 +64,8 @@ public:
   char* gets(char* s, int size);
   // wrapper for fgets, but trailing '\n' is replaced with '\0'.
   char* getsn(char* s, int size);
+  // Reads one line and returns it. The last '\n' is removed.
+  std::string getLine();
   // wrapper for fclose
   int close();
   // Return true if open_ && feof(fp_) != 0. Otherwise returns false.

+ 19 - 10
src/Netrc.cc

@@ -115,12 +115,16 @@ void Netrc::addAuthenticator(const SharedHandle<Authenticator>& authenticator)
 namespace {
 void skipMacdef(BufferedFile& fp)
 {
-  char buf[4096];
+  std::string s;
   while(1) {
-    if(!fp.gets(buf, sizeof(buf))) {
+    s = fp.getLine();
+    if(s.empty() || fp.eof()) {
       break;
     }
-    if(buf[0] == '\n' || buf[0] == '\r') {
+    if(!fp) {
+      throw DL_ABORT_EX("Netrc:I/O error.");
+    }
+    if(s[0] == '\n' || s[0] == '\r') {
       break;
     }
   }
@@ -144,18 +148,23 @@ void Netrc::parse(const std::string& path)
   };
   SharedHandle<Authenticator> authenticator;
   STATE state = GET_TOKEN;
-  char buf[4096];
   while(1) {
-    if(!fp.getsn(buf, sizeof(buf))) {
-      break;
+    std::string line = fp.getLine();
+    if(line.empty()) {
+      if(fp.eof()) {
+        break;
+      } else if(!fp) {
+        throw DL_ABORT_EX("Netrc:I/O error.");
+      } else {
+        continue;
+      }
     }
-    size_t len = strlen(buf);
-    if(len == 0 || buf[0] == '#') {
+    if(line[0] == '#') {
       continue;
     }
     std::vector<Scip> tokens;
-    util::splitIterM(&buf[0], &buf[len], std::back_inserter(tokens), " \t",
-                     true);
+    util::splitIterM(line.begin(), line.end(), std::back_inserter(tokens),
+                     " \t", true);
     for(std::vector<Scip>::const_iterator iter = tokens.begin(),
           eoi = tokens.end(); iter != eoi; ++iter) {
       if(state == GET_TOKEN) {

+ 14 - 8
src/NsCookieParser.cc

@@ -55,10 +55,11 @@ NsCookieParser::~NsCookieParser() {}
 
 namespace {
 bool parseNsCookie
-(Cookie& cookie, const char* buf, size_t buflen, time_t creationTime)
+(Cookie& cookie, const std::string& cookieStr, time_t creationTime)
 {
   std::vector<Scip> vs;
-  util::splitIter(&buf[0], &buf[buflen], std::back_inserter(vs), '\t', true);
+  util::splitIter(cookieStr.begin(), cookieStr.end(), std::back_inserter(vs),
+                  '\t', true);
   if(vs.size() < 6) {
     return false;
   }
@@ -105,17 +106,22 @@ std::vector<Cookie> NsCookieParser::parse
     throw DL_ABORT_EX(fmt("Failed to open file %s", filename.c_str()));
   }
   std::vector<Cookie> cookies;
-  char buf[8192];
   while(1) {
-    if(!fp.getsn(buf, sizeof(buf))) {
-      break;
+    std::string line = fp.getLine();
+    if(line.empty()) {
+      if(fp.eof()) {
+        break;
+      } else if(!fp) {
+        throw DL_ABORT_EX("CookieParser:I/O error.");
+      } else {
+        continue;
+      }
     }
-    size_t len = strlen(buf);
-    if(len == 0 || buf[0] == '#') {
+    if(line[0] == '#') {
       continue;
     }
     Cookie c;
-    if(parseNsCookie(c, buf, len, creationTime)) {
+    if(parseNsCookie(c, line, creationTime)) {
       cookies.push_back(c);
     }
   }

+ 7 - 6
src/ServerStatMan.cc

@@ -137,26 +137,27 @@ bool ServerStatMan::load(const std::string& filename)
                      filename.c_str()));
     return false;
   }
-  char buf[4096];
   while(1) {
-    if(!fp.getsn(buf, sizeof(buf))) {
+    std::string line = fp.getLine();
+    if(line.empty()) {
       if(fp.eof()) {
         break;
-      } else {
+      } else if(!fp) {
         A2_LOG_ERROR(fmt(MSG_READING_SERVER_STAT_FILE_FAILED,
                          filename.c_str()));
         return false;
+      } else {
+        continue;
       }
     }
     std::pair<std::string::const_iterator,
               std::string::const_iterator> p =
-      util::stripIter(&buf[0], &buf[strlen(buf)]);
+      util::stripIter(line.begin(), line.end());
     if(p.first == p.second) {
       continue;
     }
-    std::string line(p.first, p.second);
     std::vector<Scip> items;
-    util::splitIter(line.begin(), line.end(), std::back_inserter(items), ',');
+    util::splitIter(p.first, p.second, std::back_inserter(items), ',');
     std::map<std::string, std::string> m;
     for(std::vector<Scip>::const_iterator i = items.begin(),
           eoi = items.end(); i != eoi; ++i) {

+ 20 - 24
src/UriListParser.cc

@@ -55,14 +55,6 @@ UriListParser::~UriListParser() {}
 
 void UriListParser::parseNext(std::vector<std::string>& uris, Option& op)
 {
-  char buf[4096];
-  if(line_.empty()) {
-    if(!fp_.getsn(buf, sizeof(buf))) {
-      line_.clear();
-      return;
-    }
-    line_.assign(&buf[0], &buf[strlen(buf)]);
-  }
   const SharedHandle<OptionParser>& optparser = OptionParser::getInstance();
   while(1) {
     if(!line_.empty() && line_[0] != '#') {
@@ -71,31 +63,35 @@ void UriListParser::parseNext(std::vector<std::string>& uris, Option& op)
       // Read options
       std::stringstream ss;
       while(1) {
-        if(!fp_.getsn(buf, sizeof(buf))) {
-          line_.clear();
-          break;
-        }
-        line_.assign(&buf[0], &buf[strlen(buf)]);
+        line_ = fp_.getLine();
         if(line_.empty()) {
-          continue;
-        } else {
-          if(line_[0] == ' ' || line_[0] == '\t') {
-            ss << line_ << "\n";
-          } else if(line_[0] == '#') {
-            continue;
-          } else {
+          if(fp_.eof()) {
             break;
+          } else if(!fp_) {
+            throw DL_ABORT_EX("UriListParser:I/O error.");
+          } else {
+            continue;
           }
         }
+        if(line_[0] == ' ' || line_[0] == '\t') {
+          ss << line_ << "\n";
+        } else if(line_[0] == '#') {
+          continue;
+        } else {
+          break;
+        }
       }
       optparser->parse(op, ss);
       return;
     }
-    if(!fp_.getsn(buf, sizeof(buf))) {
-      line_.clear();
-      return;
+    line_ = fp_.getLine();
+    if(line_.empty()) {
+      if(fp_.eof()) {
+        return;
+      } else if(!fp_) {
+        throw DL_ABORT_EX("UriListParser:I/O error.");
+      }
     }
-    line_.assign(&buf[0], &buf[strlen(buf)]);
   }
 }