소스 검색

Introduce IOFile abstract class to refactor BufferedFile and GZipFile

IOFile provides the same interface of old BufferedFile. It provides
extension points as pure virtual functions. Those functions are
implemented by 2 concrete subclasses: BufferedFile and GZipFile.
Tatsuhiro Tsujikawa 12 년 전
부모
커밋
b0799b6e46
12개의 변경된 파일340개의 추가작업 그리고 151개의 파일을 삭제
  1. 19 73
      src/BufferedFile.cc
  2. 16 43
      src/BufferedFile.h
  3. 22 7
      src/GZipFile.cc
  4. 13 12
      src/GZipFile.h
  5. 150 0
      src/IOFile.cc
  6. 103 0
      src/IOFile.h
  7. 1 0
      src/Makefile.am
  8. 7 7
      src/SessionSerializer.cc
  9. 2 2
      src/SessionSerializer.h
  10. 2 2
      src/UriListParser.cc
  11. 2 2
      src/UriListParser.h
  12. 3 3
      test/BufferedFileTest.cc

+ 19 - 73
src/BufferedFile.cc

@@ -43,10 +43,6 @@
 
 namespace aria2 {
 
-const char BufferedFile::READ[] = "rb";
-const char BufferedFile::WRITE[] = "wb";
-const char BufferedFile::APPEND[] = "ab";
-
 BufferedFile::BufferedFile(const char* filename, const char* mode)
   :
 #ifdef __MINGW32__
@@ -67,67 +63,22 @@ BufferedFile::~BufferedFile()
   close();
 }
 
-BufferedFile::operator unspecified_bool_type() const
-{
-  bool ok = isOpen() && !isError();
-  return ok ? &BufferedFile::good_state : 0;
-}
-
-size_t BufferedFile::read(void* ptr, size_t count)
+size_t BufferedFile::onRead(void* ptr, size_t count)
 {
   return fread(ptr, 1, count, fp_);
 }
 
-size_t BufferedFile::write(const void* ptr, size_t count)
+size_t BufferedFile::onWrite(const void* ptr, size_t count)
 {
   return fwrite(ptr, 1, count, fp_);
 }
 
-size_t BufferedFile::write(const char* str)
-{
-  return write(str, strlen(str));
-}
-
-char* BufferedFile::gets(char* s, int size)
+char* BufferedFile::onGets(char* s, int size)
 {
   return fgets(s, size, fp_);
 }
 
-char* BufferedFile::getsn(char* s, int size)
-{
-  char* ptr = gets(s, size);
-  if(ptr) {
-    int len = strlen(ptr);
-    if(ptr[len-1] == '\n') {
-      ptr[len-1] = '\0';
-    }
-  }
-  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()
+int BufferedFile::onClose()
 {
   if (open_) {
     open_ = false;
@@ -136,39 +87,34 @@ int BufferedFile::close()
   return 0;
 }
 
-bool BufferedFile::eof()
+int BufferedFile::onVprintf(const char* format, va_list va)
 {
-  return !isOpen()|| isEOF();
+  return vfprintf(fp_, format, va);
 }
 
-size_t BufferedFile::transfer(std::ostream& out)
+int BufferedFile::onFlush()
 {
-  size_t count = 0;
-  char buf[4096];
-  while(1) {
-    size_t r = this->read(buf, sizeof(buf));
-    out.write(buf, r);
-    count += r;
-    if(r < sizeof(buf)) {
-      break;
-    }
-  }
-  return count;
+  return fflush(fp_);
 }
 
-int BufferedFile::vprintf(const char* format, va_list va)
+bool BufferedFile::onSupportsColor()
 {
-  return vfprintf(fp_, format, va);
+  return supportsColor_;
 }
 
-int BufferedFile::flush()
+bool BufferedFile::isError() const
 {
-  return fflush(fp_);
+  return ferror(fp_);
 }
 
-bool BufferedFile::supportsColor()
+bool BufferedFile::isEOF() const
 {
-  return supportsColor_;
+  return feof(fp_);
+}
+
+bool BufferedFile::isOpen() const
+{
+  return open_;
 }
 
 } // namespace aria2

+ 16 - 43
src/BufferedFile.h

@@ -35,69 +35,42 @@
 #ifndef D_BUFFERED_FILE_H
 #define D_BUFFERED_FILE_H
 
-#include "OutputFile.h"
+#include "IOFile.h"
 
 #include <cstdio>
-#include <string>
-#include <iosfwd>
 
 namespace aria2 {
 
-// This is a wrapper class for fopen/fclose/fread/fwrite/fgets.
-class BufferedFile:public OutputFile {
-private:
-  typedef void (BufferedFile::*unspecified_bool_type)() const;
-  void good_state() const {}
+// IOFILE implementation using standard I/O functions.
+class BufferedFile:public IOFile {
 public:
   BufferedFile(const char* filename, const char* mode);
   BufferedFile(FILE* fp);
   virtual ~BufferedFile();
-  // Returns true if file is opened and ferror returns 0. Otherwise
-  // returns false.
-  operator unspecified_bool_type() const;
+protected:
   // wrapper for fread. Using 1 for 2nd argument of fread.
-  virtual size_t read(void* ptr, size_t count);
+  virtual size_t onRead(void* ptr, size_t count);
   // wrapper for fwrite. Using 1 for 2nd argument of fwrite.
-  virtual size_t write(const void* ptr, size_t count);
-  virtual size_t write(const char* str);
+  virtual size_t onWrite(const void* ptr, size_t count);
   // wrapper for fgets
-  virtual 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
-  virtual int close();
-  // Return true if open_ && feof(fp_) != 0. Otherwise returns false.
-  bool eof();
-  // Convenient method. Read data to end of file and write them into
-  // given stream. Returns written size.
-  size_t transfer(std::ostream& out);
-  virtual int vprintf(const char* format, va_list va);
+  virtual char* onGets(char* s, int size);
+  virtual int onVprintf(const char* format, va_list va);
   // wrapper for fflush
-  virtual int flush();
-  virtual bool supportsColor();
-  // Mode for reading
-  static const char READ[];
-  // Mode for writing
-  static const char WRITE[];
-  // Mode for append
-  static const char APPEND[];
-
+  virtual int onFlush();
+  // wrapper for fclose
+  virtual int onClose();
+  virtual bool onSupportsColor();
+  virtual bool isError() const;
+  virtual bool isEOF() const;
+  virtual bool isOpen() const;
 private:
-  // Don't allow copying
+  // Don't allow copying;
   BufferedFile(const BufferedFile&);
   BufferedFile& operator=(const BufferedFile&);
 
   FILE* fp_;
   bool open_;
   bool supportsColor_;
-
-protected:
-  virtual bool isError() const { return ferror(fp_); }
-  virtual bool isEOF() const { return feof(fp_); }
-  virtual bool isOpen() const { return open_; }
-
 };
 
 } // namespace aria2

+ 22 - 7
src/GZipFile.cc

@@ -44,7 +44,7 @@
 namespace aria2 {
 
 GZipFile::GZipFile(const char* filename, const char* mode)
-  : BufferedFile(0), fp_(0), open_(false),
+  : fp_(0), open_(false),
     buflen_(1024), buf_(reinterpret_cast<char*>(malloc(buflen_)))
 {
   FILE* fp =
@@ -81,7 +81,7 @@ GZipFile::~GZipFile()
   free(buf_);
 }
 
-int GZipFile::close()
+int GZipFile::onClose()
 {
   if (open_) {
     open_ = false;
@@ -90,6 +90,11 @@ int GZipFile::close()
   return 0;
 }
 
+bool GZipFile::onSupportsColor()
+{
+  return false;
+}
+
 bool GZipFile::isError() const
 {
   int rv = 0;
@@ -97,7 +102,17 @@ bool GZipFile::isError() const
   return (e != 0 && *e != 0) || rv != 0;
 }
 
-size_t GZipFile::read(void* ptr, size_t count)
+bool GZipFile::isEOF() const
+{
+  return gzeof(fp_);
+}
+
+bool GZipFile::isOpen() const
+{
+  return open_;
+}
+
+size_t GZipFile::onRead(void* ptr, size_t count)
 {
   char *data = reinterpret_cast<char*>(ptr);
   size_t read = 0;
@@ -114,7 +129,7 @@ size_t GZipFile::read(void* ptr, size_t count)
   return read;
 }
 
-size_t GZipFile::write(const void* ptr, size_t count)
+size_t GZipFile::onWrite(const void* ptr, size_t count)
 {
   const char *data = reinterpret_cast<const char*>(ptr);
   size_t written = 0;
@@ -131,17 +146,17 @@ size_t GZipFile::write(const void* ptr, size_t count)
   return written;
 }
 
-char* GZipFile::gets(char* s, int size)
+char* GZipFile::onGets(char* s, int size)
 {
   return gzgets(fp_, s, size);
 }
 
-int GZipFile::flush()
+int GZipFile::onFlush()
 {
   return gzflush(fp_, 0);
 }
 
-int GZipFile::vprintf(const char* format, va_list va)
+int GZipFile::onVprintf(const char* format, va_list va)
 {
   ssize_t len;
 #ifdef __MINGW32__

+ 13 - 12
src/GZipFile.h

@@ -38,20 +38,25 @@
 
 #include <zlib.h>
 
-#include "BufferedFile.h"
+#include "IOFile.h"
 
 namespace aria2 {
 
-class GZipFile: public BufferedFile {
+class GZipFile: public IOFile {
 public:
   GZipFile(const char* filename, const char* mode);
   virtual ~GZipFile();
-  virtual int close();
-  virtual size_t read(void* ptr, size_t count);
-  virtual size_t write(const void* ptr, size_t count);
-  virtual char* gets(char* s, int size);
-  virtual int vprintf(const char* format, va_list va);
-  virtual int flush();
+protected:
+  virtual size_t onRead(void* ptr, size_t count);
+  virtual size_t onWrite(const void* ptr, size_t count);
+  virtual char* onGets(char* s, int size);
+  virtual int onVprintf(const char* format, va_list va);
+  virtual int onFlush();
+  virtual int onClose();
+  virtual bool onSupportsColor();
+  virtual bool isError() const;
+  virtual bool isEOF() const;
+  virtual bool isOpen() const;
 private:
   // Don't allow copying
   GZipFile(const GZipFile&);
@@ -62,10 +67,6 @@ private:
 
   size_t buflen_;
   char* buf_;
-protected:
-  virtual bool isError() const;
-  virtual bool isEOF() const { return gzeof(fp_); }
-  virtual bool isOpen() const { return open_; }
 };
 
 } // namespace aria2

+ 150 - 0
src/IOFile.cc

@@ -0,0 +1,150 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "IOFile.h"
+
+#include <cstring>
+#include <cstdarg>
+#include <ostream>
+
+#include "a2io.h"
+#include "util.h"
+
+namespace aria2 {
+
+const char IOFile::READ[] = "rb";
+const char IOFile::WRITE[] = "wb";
+const char IOFile::APPEND[] = "ab";
+
+IOFile::operator unspecified_bool_type() const
+{
+  bool ok = isOpen() && !isError();
+  return ok ? &IOFile::goodState : 0;
+}
+
+size_t IOFile::read(void* ptr, size_t count)
+{
+  return onRead(ptr, count);
+}
+
+size_t IOFile::write(const void* ptr, size_t count)
+{
+  return onWrite(ptr, count);
+}
+
+size_t IOFile::write(const char* str)
+{
+  return write(str, strlen(str));
+}
+
+char* IOFile::gets(char* s, int size)
+{
+  return onGets(s, size);
+}
+
+char* IOFile::getsn(char* s, int size)
+{
+  char* ptr = gets(s, size);
+  if(ptr) {
+    int len = strlen(ptr);
+    if(ptr[len-1] == '\n') {
+      ptr[len-1] = '\0';
+    }
+  }
+  return ptr;
+}
+
+std::string IOFile::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 IOFile::close()
+{
+  return onClose();
+}
+
+bool IOFile::eof()
+{
+  return !isOpen() || isEOF();
+}
+
+size_t IOFile::transfer(std::ostream& out)
+{
+  size_t count = 0;
+  char buf[4096];
+  while(1) {
+    size_t r = this->read(buf, sizeof(buf));
+    out.write(buf, r);
+    count += r;
+    if(r < sizeof(buf)) {
+      break;
+    }
+  }
+  return count;
+}
+
+int IOFile::vprintf(const char* format, va_list va)
+{
+  return onVprintf(format, va);
+}
+
+int IOFile::flush()
+{
+  return onFlush();
+}
+
+bool IOFile::supportsColor()
+{
+  return onSupportsColor();
+}
+
+} // namespace aria2

+ 103 - 0
src/IOFile.h

@@ -0,0 +1,103 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2011 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef D_IO_FILE_H
+#define D_IO_FILE_H
+
+#include "OutputFile.h"
+
+#include <string>
+#include <iosfwd>
+
+namespace aria2 {
+
+// This is a wrapper base class intended to provide
+// fopen/fclose/fread/fwrite/fgets functionality.
+class IOFile:public OutputFile {
+private:
+  typedef void (IOFile::*unspecified_bool_type)() const;
+  void goodState() const {}
+public:
+  IOFile() {}
+  virtual ~IOFile() {}
+  // 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);
+  // wrapper for fwrite. Using 1 for 2nd argument of fwrite.
+  size_t write(const void* ptr, size_t count);
+  virtual size_t write(const char* str);
+  // wrapper for fgets
+  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();
+  // wrapper for fflush
+  int flush();
+  // Return true if file is opened && feof(fp_) != 0. Otherwise
+  // returns false.
+  bool eof();
+  // Returns true if file supports ANSI color escape codes.
+  bool supportsColor();
+  // Convenient method. Read data to end of file and write them into
+  // given stream. Returns written size.
+  size_t transfer(std::ostream& out);
+  int vprintf(const char* format, va_list va);
+  // Mode for reading
+  static const char READ[];
+  // Mode for writing
+  static const char WRITE[];
+  // Mode for append
+  static const char APPEND[];
+protected:
+  virtual size_t onRead(void* ptr, size_t count) = 0;
+  virtual size_t onWrite(const void* ptr, size_t count) = 0;
+  virtual char* onGets(char* s, int size) = 0;
+  virtual int onVprintf(const char* format, va_list va) = 0;
+  virtual int onFlush() = 0;
+  virtual int onClose() = 0;
+  virtual bool onSupportsColor() = 0;
+
+  virtual bool isError() const = 0;
+  virtual bool isEOF() const = 0;
+  virtual bool isOpen() const = 0;
+};
+
+} // namespace aria2
+
+#endif // D_IO_FILE_H

+ 1 - 0
src/Makefile.am

@@ -229,6 +229,7 @@ SRCS =  option_processing.cc\
 	OutputFile.h\
 	NullOutputFile.h\
 	console.cc console.h\
+	IOFile.cc IOFile.h\
 	BufferedFile.cc BufferedFile.h\
 	SegList.h\
 	NullHandle.h\

+ 7 - 7
src/SessionSerializer.cc

@@ -70,15 +70,15 @@ bool SessionSerializer::save(const std::string& filename) const
   std::string tempFilename = filename;
   tempFilename += "__temp";
   {
-    SharedHandle<BufferedFile> fp;
+    SharedHandle<IOFile> fp;
 #if HAVE_ZLIB
     if (util::endsWith(filename, ".gz")) {
-      fp.reset(new GZipFile(tempFilename.c_str(), BufferedFile::WRITE));
+      fp.reset(new GZipFile(tempFilename.c_str(), IOFile::WRITE));
     }
     else
 #endif
     {
-     fp.reset(new BufferedFile(tempFilename.c_str(), BufferedFile::WRITE));
+     fp.reset(new BufferedFile(tempFilename.c_str(), IOFile::WRITE));
     }
     if(!*fp) {
       return false;
@@ -93,7 +93,7 @@ bool SessionSerializer::save(const std::string& filename) const
 namespace {
 // Write 1 line of option name/value pair. This function returns true
 // if it succeeds, or false.
-bool writeOptionLine(BufferedFile& fp, const Pref* pref,
+bool writeOptionLine(IOFile& fp, const Pref* pref,
                      const std::string& val)
 {
   size_t prefLen = strlen(pref->k);
@@ -106,7 +106,7 @@ bool writeOptionLine(BufferedFile& fp, const Pref* pref,
 } // namespace
 
 namespace {
-bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
+bool writeOption(IOFile& fp, const SharedHandle<Option>& op)
 {
   const SharedHandle<OptionParser>& oparser = OptionParser::getInstance();
   for(size_t i = 1, len = option::countOption(); i < len; ++i) {
@@ -151,7 +151,7 @@ bool writeOption(BufferedFile& fp, const SharedHandle<Option>& op)
 
 namespace {
 bool writeDownloadResult
-(BufferedFile& fp, std::set<a2_gid_t>& metainfoCache,
+(IOFile& fp, std::set<a2_gid_t>& metainfoCache,
  const SharedHandle<DownloadResult>& dr)
 {
   const SharedHandle<MetadataInfo>& mi = dr->metadataInfo;
@@ -211,7 +211,7 @@ bool writeDownloadResult
 }
 } // namespace
 
-bool SessionSerializer::save(BufferedFile& fp) const
+bool SessionSerializer::save(IOFile& fp) const
 {
   std::set<a2_gid_t> metainfoCache;
   const DownloadResultList& results = rgman_->getDownloadResults();

+ 2 - 2
src/SessionSerializer.h

@@ -45,7 +45,7 @@
 namespace aria2 {
 
 class RequestGroupMan;
-class BufferedFile;
+class IOFile;
 
 class SessionSerializer {
 private:
@@ -53,7 +53,7 @@ private:
   bool saveError_;
   bool saveInProgress_;
   bool saveWaiting_;
-  bool save(BufferedFile& fp) const;
+  bool save(IOFile& fp) const;
 public:
   SessionSerializer(const SharedHandle<RequestGroupMan>& requestGroupMan);
 

+ 2 - 2
src/UriListParser.cc

@@ -53,9 +53,9 @@ namespace aria2 {
 
 UriListParser::UriListParser(const std::string& filename)
 #if HAVE_ZLIB
-  : fp_(new GZipFile(filename.c_str(), BufferedFile::READ))
+  : fp_(new GZipFile(filename.c_str(), IOFile::READ))
 #else
-  : fp_(new BufferedFile(filename.c_str(), BufferedFile::READ))
+  : fp_(new BufferedFile(filename.c_str(), IOFile::READ))
 #endif
 {}
 

+ 2 - 2
src/UriListParser.h

@@ -42,14 +42,14 @@
 #include <iosfwd>
 
 #include "Option.h"
-#include "BufferedFile.h"
+#include "IOFile.h"
 #include "SharedHandle.h"
 
 namespace aria2 {
 
 class UriListParser {
 private:
-  SharedHandle<BufferedFile> fp_;
+  SharedHandle<IOFile> fp_;
 
   std::string line_;
 public:

+ 3 - 3
test/BufferedFileTest.cc

@@ -24,16 +24,16 @@ void BufferedFileTest::testOpen()
 {
   File f(A2_TEST_OUT_DIR"/aria2_BufferedFileTest_testOpen");
   f.remove();
-  BufferedFile fail(f.getPath().c_str(), BufferedFile::READ);
+  BufferedFile fail(f.getPath().c_str(), IOFile::READ);
   CPPUNIT_ASSERT(!fail);
 
-  BufferedFile wr(f.getPath().c_str(),  BufferedFile::WRITE);
+  BufferedFile wr(f.getPath().c_str(),  IOFile::WRITE);
   CPPUNIT_ASSERT(wr);
   std::string msg = "aria2 rules\nalpha\nbravo\ncharlie";
   wr.write(msg.data(), msg.size());
   wr.close();
 
-  BufferedFile rd(f.getPath().c_str(), BufferedFile::READ);
+  BufferedFile rd(f.getPath().c_str(), IOFile::READ);
   char buf[256];
   size_t len = rd.read(buf, 11);
   CPPUNIT_ASSERT_EQUAL((size_t)11, len);