diff options
| author | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-08-09 23:33:55 +0900 |
|---|---|---|
| committer | Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> | 2011-08-09 23:33:55 +0900 |
| commit | a10cda2f17916895d8c6bc3cd69a360947017771 (patch) | |
| tree | 0740833f77a3e239ea58e870a9dcb9086d43e516 /src | |
| parent | 02307cee0a395d8405d0e160664d4a37c79fe16c (diff) | |
Use global::cout to output string to stdout.
In MinGW32 build, global::cout is WinConsoleFile. When outputing to
console, it uses WriteConsoleW, so Unicode characters are written.
Fixed memory leak in WChar<->MultiByte conversion functions. The
portion of code which uses std::cout is rewritten to use global::cout.
Diffstat (limited to 'src')
| -rw-r--r-- | src/BufferedFile.cc | 5 | ||||
| -rw-r--r-- | src/BufferedFile.h | 11 | ||||
| -rw-r--r-- | src/ConsoleStatCalc.cc | 44 | ||||
| -rw-r--r-- | src/FileEntry.h | 4 | ||||
| -rw-r--r-- | src/Logger.cc | 36 | ||||
| -rw-r--r-- | src/Logger.h | 7 | ||||
| -rw-r--r-- | src/Makefile.am | 9 | ||||
| -rw-r--r-- | src/MultiUrlRequestInfo.cc | 16 | ||||
| -rw-r--r-- | src/MultiUrlRequestInfo.h | 6 | ||||
| -rw-r--r-- | src/NullOutputFile.h | 52 | ||||
| -rw-r--r-- | src/OutputFile.h | 54 | ||||
| -rw-r--r-- | src/Platform.cc | 3 | ||||
| -rw-r--r-- | src/RequestGroupMan.cc | 36 | ||||
| -rw-r--r-- | src/RequestGroupMan.h | 10 | ||||
| -rw-r--r-- | src/WinConsoleFile.cc | 105 | ||||
| -rw-r--r-- | src/WinConsoleFile.h | 58 | ||||
| -rw-r--r-- | src/bittorrent_helper.cc | 48 | ||||
| -rw-r--r-- | src/bittorrent_helper.h | 55 | ||||
| -rw-r--r-- | src/console.cc | 58 | ||||
| -rw-r--r-- | src/console.h | 62 | ||||
| -rw-r--r-- | src/main.cc | 25 | ||||
| -rw-r--r-- | src/util.cc | 60 | ||||
| -rw-r--r-- | src/util.h | 24 |
23 files changed, 605 insertions, 183 deletions
diff --git a/src/BufferedFile.cc b/src/BufferedFile.cc index 812704c9..1bca85f4 100644 --- a/src/BufferedFile.cc +++ b/src/BufferedFile.cc @@ -77,6 +77,11 @@ size_t BufferedFile::write(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) { return fgets(s, size, fp_); diff --git a/src/BufferedFile.h b/src/BufferedFile.h index b5308c0c..db006c8a 100644 --- a/src/BufferedFile.h +++ b/src/BufferedFile.h @@ -35,7 +35,7 @@ #ifndef D_BUFFERED_FILE_H #define D_BUFFERED_FILE_H -#include "common.h" +#include "OutputFile.h" #include <cstdio> #include <string> @@ -44,14 +44,14 @@ namespace aria2 { // This is a wrapper class for fopen/fclose/fread/fwrite/fgets. -class BufferedFile { +class BufferedFile:public OutputFile { private: typedef void (BufferedFile::*unspecified_bool_type)() const; void good_state() const {} public: BufferedFile(const std::string& filename, const std::string& mode); BufferedFile(FILE* fp); - ~BufferedFile(); + virtual ~BufferedFile(); // Returns true if file is opened and both ferror and feof returns // 0. Otherwise returns false. operator unspecified_bool_type() const; @@ -59,6 +59,7 @@ public: 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'. @@ -71,9 +72,9 @@ public: // given stream. Returns written size. size_t transfer(std::ostream& out); // wrapper for fprintf - int printf(const char* format, ...); + virtual int printf(const char* format, ...); // wrapper for fflush - int flush(); + virtual int flush(); // Mode for reading static const std::string READ; // Mode for writing diff --git a/src/ConsoleStatCalc.cc b/src/ConsoleStatCalc.cc index c8969f16..5710b184 100644 --- a/src/ConsoleStatCalc.cc +++ b/src/ConsoleStatCalc.cc @@ -61,6 +61,7 @@ #include "DownloadContext.h" #include "wallclock.h" #include "FileEntry.h" +#include "console.h" #ifdef ENABLE_BITTORRENT # include "bittorrent_helper.h" # include "PeerStorage.h" @@ -185,15 +186,17 @@ public: void operator()(const SharedHandle<RequestGroup>& rg) { const char SEP_CHAR = '-'; - printProgress(std::cout, rg, e_, sizeFormatter_); + std::stringstream o; + printProgress(o, rg, e_, sizeFormatter_); const std::vector<SharedHandle<FileEntry> >& fileEntries = rg->getDownloadContext()->getFileEntries(); - std::cout << "\n" - << "FILE: "; + o << "\n" + << "FILE: "; writeFilePath(fileEntries.begin(), fileEntries.end(), - std::cout, rg->inMemoryDownload()); - std::cout << "\n" - << std::setfill(SEP_CHAR) << std::setw(cols_) << SEP_CHAR << "\n"; + o, rg->inMemoryDownload()); + o << "\n" + << std::setfill(SEP_CHAR) << std::setw(cols_) << SEP_CHAR << "\n"; + global::cout->write(o.str().c_str()); } }; } // namespace @@ -207,7 +210,8 @@ void printProgressSummary const char SEP_CHAR = '='; time_t now; time(&now); - std::cout << " *** Download Progress Summary"; + std::stringstream o; + o << " *** Download Progress Summary"; { time_t now; struct tm* staticNowtmPtr; @@ -218,11 +222,12 @@ void printProgressSummary if(lfptr) { *lfptr = '\0'; } - std::cout << " as of " << buf; + o << " as of " << buf; } } - std::cout << " *** " << "\n" - << std::setfill(SEP_CHAR) << std::setw(cols) << SEP_CHAR << "\n"; + o << " *** " << "\n" + << std::setfill(SEP_CHAR) << std::setw(cols) << SEP_CHAR << "\n"; + global::cout->write(o.str().c_str()); std::for_each(groups.begin(), groups.end(), PrintSummary(cols, e, sizeFormatter)); } @@ -267,7 +272,8 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) } #endif // HAVE_TERMIOS_H #endif // !__MINGW32__ - std::cout << '\r' << std::setfill(' ') << std::setw(cols) << ' ' << '\r'; + std::string line(cols, ' '); + global::cout->printf("\r%s\r", line.c_str()); } std::ostringstream o; if(e->getRequestGroupMan()->countRequestGroup() > 0) { @@ -277,7 +283,8 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) lastSummaryNotified_ = global::wallclock; printProgressSummary(e->getRequestGroupMan()->getRequestGroups(), cols, e, sizeFormatter); - std::cout << "\n"; + global::cout->write("\n"); + global::cout->flush(); } } if(!readoutVisibility_) { @@ -362,17 +369,14 @@ ConsoleStatCalc::calculateStat(const DownloadEngine* e) #endif // ENABLE_MESSAGE_DIGEST std::string readout = o.str(); if(isTTY) { - std::string::iterator last = readout.begin(); if(truncate_ && readout.size() > cols) { - std::advance(last, cols); - } else { - last = readout.end(); + readout[cols] = '\0'; } - std::copy(readout.begin(), last, std::ostream_iterator<char>(std::cout)); - std::cout << std::flush; + global::cout->write(readout.c_str()); + global::cout->flush(); } else { - std::copy(readout.begin(), readout.end(), std::ostream_iterator<char>(std::cout)); - std::cout << std::endl; + global::cout->write(readout.c_str()); + global::cout->write("\n"); } } diff --git a/src/FileEntry.h b/src/FileEntry.h index ce202d57..f7d23f38 100644 --- a/src/FileEntry.h +++ b/src/FileEntry.h @@ -317,9 +317,9 @@ void writeFilePath } } else { if(memory) { - o << "[MEMORY]" << utf8ToNative(File(e->getPath()).getBasename()); + o << "[MEMORY]" << File(e->getPath()).getBasename(); } else { - o << utf8ToNative(e->getPath()); + o << e->getPath(); } size_t count = countRequestedFileEntry(first, last); if(count > 1) { diff --git a/src/Logger.cc b/src/Logger.cc index be167f18..3f88451b 100644 --- a/src/Logger.cc +++ b/src/Logger.cc @@ -44,6 +44,7 @@ #include "a2time.h" #include "BufferedFile.h" #include "util.h" +#include "console.h" namespace aria2 { @@ -61,31 +62,30 @@ static const std::string ERROR_LABEL("ERROR"); Logger::Logger() : logLevel_(Logger::A2_DEBUG), - fpp_(0), - stdoutfpp_(new BufferedFile(stdout)), stdoutField_(0) {} Logger::~Logger() { - delete fpp_; - delete stdoutfpp_; } void Logger::openFile(const std::string& filename) { closeFile(); - fpp_ = new BufferedFile(filename, BufferedFile::APPEND); - if(!fpp_) { - throw DL_ABORT_EX(fmt(EX_FILE_OPEN, filename.c_str(), "n/a")); + if(filename == DEV_STDOUT) { + fpp_ = global::cout; + } else { + fpp_.reset(new BufferedFile(filename, BufferedFile::APPEND)); + if(!fpp_) { + throw DL_ABORT_EX(fmt(EX_FILE_OPEN, filename.c_str(), "n/a")); + } } } void Logger::closeFile() { if(fpp_) { - fpp_->close(); - fpp_ = 0; + fpp_.reset(); } } @@ -124,8 +124,9 @@ const std::string& levelToString(Logger::LEVEL level) } // namespace namespace { +template<typename Output> void writeHeader -(BufferedFile& fp, Logger::LEVEL level, const char* sourceFile, int lineNum) +(Output& fp, Logger::LEVEL level, const char* sourceFile, int lineNum) { struct timeval tv; gettimeofday(&tv, 0); @@ -146,9 +147,10 @@ void writeHeader } // namespace namespace { -void writeStackTrace(BufferedFile& fp, const std::string& stackTrace) +template<typename Output> +void writeStackTrace(Output& fp, const std::string& stackTrace) { - fp.write(stackTrace.data(), stackTrace.size()); + fp.write(stackTrace.c_str()); } } // namespace @@ -168,11 +170,11 @@ void Logger::writeLog fpp_->flush(); } if(toConsole) { - stdoutfpp_->write("\n", 1); - writeHeader(*stdoutfpp_, level, 0, 0); - stdoutfpp_->printf("%s\n", msg); - writeStackTrace(*stdoutfpp_, trace); - stdoutfpp_->flush(); + global::cout->printf("\n"); + writeHeader(*global::cout, level, 0, 0); + global::cout->printf("%s\n", msg); + writeStackTrace(*global::cout, trace); + global::cout->flush(); } } diff --git a/src/Logger.h b/src/Logger.h index dc955247..fb7068bc 100644 --- a/src/Logger.h +++ b/src/Logger.h @@ -39,10 +39,12 @@ #include <string> +#include "SharedHandle.h" + namespace aria2 { class Exception; -class BufferedFile; +class OutputFile; class Logger { public: @@ -55,8 +57,7 @@ public: }; private: LEVEL logLevel_; - BufferedFile* fpp_; - BufferedFile* stdoutfpp_; + SharedHandle<OutputFile> fpp_; int stdoutField_; // Don't allow copying Logger(const Logger&); diff --git a/src/Makefile.am b/src/Makefile.am index 64ccb3ea..67833bf9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -225,7 +225,14 @@ SRCS = Socket.h\ StreamPieceSelector.h\ DefaultStreamPieceSelector.cc DefaultStreamPieceSelector.h\ InorderStreamPieceSelector.cc InorderStreamPieceSelector.h\ - MetalinkHttpEntry.cc MetalinkHttpEntry.h + MetalinkHttpEntry.cc MetalinkHttpEntry.h\ + OutputFile.h\ + NullOutputFile.h\ + console.cc console.h + +if MINGW_BUILD +SRCS += WinConsoleFile.cc WinConsoleFile.h +endif # MINGW_BUILD if ENABLE_XML_RPC SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\ diff --git a/src/MultiUrlRequestInfo.cc b/src/MultiUrlRequestInfo.cc index 760fe7e5..27659aa4 100644 --- a/src/MultiUrlRequestInfo.cc +++ b/src/MultiUrlRequestInfo.cc @@ -59,6 +59,7 @@ #include "TimeA2.h" #include "fmt.h" #include "SocketCore.h" +#include "OutputFile.h" #ifdef ENABLE_SSL # include "TLSContext.h" #endif // ENABLE_SSL @@ -142,7 +143,7 @@ MultiUrlRequestInfo::MultiUrlRequestInfo (const std::vector<SharedHandle<RequestGroup> >& requestGroups, const SharedHandle<Option>& op, const SharedHandle<StatCalc>& statCalc, - std::ostream& summaryOut) + const SharedHandle<OutputFile>& summaryOut) : requestGroups_(requestGroups), option_(op), statCalc_(statCalc), @@ -153,11 +154,10 @@ MultiUrlRequestInfo::~MultiUrlRequestInfo() {} void MultiUrlRequestInfo::printMessageForContinue() { - summaryOut_ << "\n" - << _("aria2 will resume download if the transfer is restarted.") - << "\n" - << _("If there are any errors, then see the log file. See '-l' option in help/man page for details.") - << "\n"; + summaryOut_->printf + ("\n%s\n%s\n", + _("aria2 will resume download if the transfer is restarted."), + _("If there are any errors, then see the log file. See '-l' option in help/man page for details.")); } error_code::Value MultiUrlRequestInfo::execute() @@ -251,8 +251,8 @@ error_code::Value MultiUrlRequestInfo::execute() if(!serverStatOf.empty()) { e->getRequestGroupMan()->saveServerStat(serverStatOf); } - e->getRequestGroupMan()->showDownloadResults(summaryOut_); - summaryOut_ << std::flush; + e->getRequestGroupMan()->showDownloadResults(*summaryOut_); + summaryOut_->flush(); RequestGroupMan::DownloadStat s = e->getRequestGroupMan()->getDownloadStat(); diff --git a/src/MultiUrlRequestInfo.h b/src/MultiUrlRequestInfo.h index bb84ffc6..f5eca97a 100644 --- a/src/MultiUrlRequestInfo.h +++ b/src/MultiUrlRequestInfo.h @@ -38,7 +38,6 @@ #include "common.h" #include <vector> -#include <iosfwd> #include "SharedHandle.h" #include "DownloadResult.h" @@ -48,6 +47,7 @@ namespace aria2 { class RequestGroup; class Option; class StatCalc; +class OutputFile; class MultiUrlRequestInfo { private: @@ -57,7 +57,7 @@ private: SharedHandle<StatCalc> statCalc_; - std::ostream& summaryOut_; + SharedHandle<OutputFile> summaryOut_; void printMessageForContinue(); public: @@ -65,7 +65,7 @@ public: (const std::vector<SharedHandle<RequestGroup> >& requestGroups, const SharedHandle<Option>& op, const SharedHandle<StatCalc>& statCalc, - std::ostream& summaryOut); + const SharedHandle<OutputFile>& summaryOut); virtual ~MultiUrlRequestInfo(); diff --git a/src/NullOutputFile.h b/src/NullOutputFile.h new file mode 100644 index 00000000..9ee29b78 --- /dev/null +++ b/src/NullOutputFile.h @@ -0,0 +1,52 @@ +/* <!-- 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_NULL_OUTPUT_FILE_H +#define D_NULL_OUTPUT_FILE_H + +#include "OutputFile.h" + +namespace aria2 { + +class NullOutputFile:public OutputFile { +public: + virtual ~NullOutputFile() {} + virtual size_t write(const char* str) { return 0; } + virtual int printf(const char* format, ...) { return 0; } + virtual int flush() { return 0; } +}; + +} // namespace aria2 + +#endif // D_NULL_OUTPUT_FILE_H diff --git a/src/OutputFile.h b/src/OutputFile.h new file mode 100644 index 00000000..66d1e729 --- /dev/null +++ b/src/OutputFile.h @@ -0,0 +1,54 @@ +/* <!-- 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_OUTPUT_FILE_H +#define D_OUTPUT_FILE_H + +#include "common.h" + +#include <cstdlib> + +namespace aria2 { + +class OutputFile { +public: + virtual ~OutputFile() {} + virtual size_t write(const char* str) = 0; + virtual int printf(const char* format, ...) = 0; + virtual int flush() = 0; +}; + +} // namespace aria2 + +#endif // D_OUTPUT_FILE_H diff --git a/src/Platform.cc b/src/Platform.cc index b0e315a3..dfcaebd9 100644 --- a/src/Platform.cc +++ b/src/Platform.cc @@ -72,6 +72,7 @@ #include "DlAbortEx.h" #include "message.h" #include "fmt.h" +#include "console.h" namespace aria2 { @@ -94,6 +95,8 @@ bool Platform::setUp() } initialized_ = true; + global::initConsole(); + #ifdef ENABLE_NLS setlocale (LC_CTYPE, ""); setlocale (LC_MESSAGES, ""); diff --git a/src/RequestGroupMan.cc b/src/RequestGroupMan.cc index bed2d927..0eef1caf 100644 --- a/src/RequestGroupMan.cc +++ b/src/RequestGroupMan.cc @@ -38,7 +38,6 @@ #include <cstring> #include <iomanip> #include <sstream> -#include <ostream> #include <numeric> #include <algorithm> #include <utility> @@ -74,6 +73,7 @@ #include "uri.h" #include "Triplet.h" #include "Signature.h" +#include "OutputFile.h" namespace aria2 { @@ -588,7 +588,7 @@ RequestGroupMan::DownloadStat RequestGroupMan::getDownloadStat() const lastError); } -void RequestGroupMan::showDownloadResults(std::ostream& o) const +void RequestGroupMan::showDownloadResults(OutputFile& o) const { static const std::string MARK_OK("OK"); static const std::string MARK_ERR("ERR"); @@ -598,16 +598,17 @@ void RequestGroupMan::showDownloadResults(std::ostream& o) const // Download Results: // idx|stat|path/length // ===+====+======================================================================= - o << "\n" - <<_("Download Results:") << "\n" - << "gid|stat|avg speed |path/URI" << "\n" - << "===+====+===========+"; + o.printf("\n%s" + "\ngid|stat|avg speed |path/URI" + "\n===+====+===========+", + _("Download Results:")); #ifdef __MINGW32__ int pathRowSize = 58; #else // !__MINGW32__ int pathRowSize = 59; #endif // !__MINGW32__ - o << std::setfill('=') << std::setw(pathRowSize) << '=' << "\n"; + std::string line(pathRowSize, '='); + o.printf("%s\n", line.c_str()); int ok = 0; int err = 0; int inpr = 0; @@ -632,29 +633,30 @@ void RequestGroupMan::showDownloadResults(std::ostream& o) const status = MARK_ERR; ++err; } - o << formatDownloadResult(status, *itr) << "\n"; + o.write(formatDownloadResult(status, *itr).c_str()); + o.write("\n"); } if(ok > 0 || err > 0 || inpr > 0 || rm > 0) { - o << "\n" - << _("Status Legend:") << "\n"; - + o.printf("\n%s\n", _("Status Legend:")); if(ok > 0) { - o << " (OK):download completed."; + o.write(" (OK):download completed."); } if(err > 0) { - o << "(ERR):error occurred."; + o.write("(ERR):error occurred."); } if(inpr > 0) { - o << "(INPR):download in-progress."; + o.write("(INPR):download in-progress."); } if(rm > 0) { - o << "(RM):download removed."; + o.write("(RM):download removed."); } - o << "\n"; + o.write("\n"); } } -std::string RequestGroupMan::formatDownloadResult(const std::string& status, const DownloadResultHandle& downloadResult) const +std::string RequestGroupMan::formatDownloadResult +(const std::string& status, + const DownloadResultHandle& downloadResult) const { std::stringstream o; o << std::setw(3) << downloadResult->gid << "|" diff --git a/src/RequestGroupMan.h b/src/RequestGroupMan.h index ab3da333..fc243f05 100644 --- a/src/RequestGroupMan.h +++ b/src/RequestGroupMan.h @@ -39,7 +39,6 @@ #include <string> #include <deque> -#include <iosfwd> #include <vector> #include "SharedHandle.h" @@ -55,6 +54,7 @@ struct DownloadResult; class ServerStatMan; class ServerStat; class Option; +class OutputFile; class RequestGroupMan { private: @@ -85,9 +85,9 @@ private: size_t maxDownloadResult_; - std::string - formatDownloadResult(const std::string& status, - const SharedHandle<DownloadResult>& downloadResult) const; + std::string formatDownloadResult + (const std::string& status, + const DownloadResultHandle& downloadResult) const; void configureRequestGroup (const SharedHandle<RequestGroup>& requestGroup) const; @@ -160,7 +160,7 @@ public: bool removeReservedGroup(a2_gid_t gid); - void showDownloadResults(std::ostream& o) const; + void showDownloadResults(OutputFile& o) const; bool isSameFileBeingDownloaded(RequestGroup* requestGroup) const; diff --git a/src/WinConsoleFile.cc b/src/WinConsoleFile.cc new file mode 100644 index 00000000..81755fe1 --- /dev/null +++ b/src/WinConsoleFile.cc @@ -0,0 +1,105 @@ +/* <!-- 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 "WinConsoleFile.h" + +#include <cstring> +#include <cstdio> +#include <cstdarg> +#include <string> + +#ifdef __MINGW32__ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif // __MINGW32__ + +#include "a2io.h" +#include "util.h" + +namespace aria2 { + +WinConsoleFile::WinConsoleFile() {} + +WinConsoleFile::~WinConsoleFile() {} + +namespace { +bool console() +{ + DWORD mode; + return GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &mode); +} +} // namespace + +size_t WinConsoleFile::write(const char* str) +{ + DWORD written; + if(console()) { + std::wstring msg = utf8ToWChar(str); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), + msg.c_str(), msg.size(), &written, 0); + } else { + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + str, strlen(str), &written, 0); + } + return written; +} + +int WinConsoleFile::printf(const char* format, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, format); + int r = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if(r <= 0) { + return 0; + } + DWORD written; + if(console()) { + std::wstring msg = utf8ToWChar(buf); + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), + msg.c_str(), msg.size(), &written, 0); + } else { + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + buf, r, &written, 0); + } + return written; +} + +int WinConsoleFile::flush() +{ + return 0; +} + +} // namespace aria2 diff --git a/src/WinConsoleFile.h b/src/WinConsoleFile.h new file mode 100644 index 00000000..56d750eb --- /dev/null +++ b/src/WinConsoleFile.h @@ -0,0 +1,58 @@ +/* <!-- 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_WIN_CONSOLE_FILE_H +#define D_WIN_CONSOLE_FILE_H + +#include "OutputFile.h" + +namespace aria2 { + +// This is a wrapper class for WriteConsoleW +class WinConsoleFile:public OutputFile { +public: + WinConsoleFile(); + virtual ~WinConsoleFile(); + virtual size_t write(const char* str); + virtual int printf(const char* format, ...); + virtual int flush(); +private: + // Don't allow copying + WinConsoleFile(const WinConsoleFile&); + WinConsoleFile& operator=(const WinConsoleFile&); +}; + +} // namespace aria2 + +#endif // D_WIN_CONSOLE_FILE_H diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 790ae82d..8519995d 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -611,54 +611,6 @@ getInfoHashString(const SharedHandle<DownloadContext>& dctx) return util::toHex(getTorrentAttrs(dctx)->infoHash); } -void print(std::ostream& o, const SharedHandle<DownloadContext>& dctx) -{ - SharedHandle<TorrentAttribute> torrentAttrs = getTorrentAttrs(dctx); - o << "*** BitTorrent File Information ***" << "\n"; - if(!torrentAttrs->comment.empty()) { - o << "Comment: " << torrentAttrs->comment << "\n"; - } - if(torrentAttrs->creationDate) { - o << "Creation Date: " << Time(torrentAttrs->creationDate).toHTTPDate() - << std::endl; - } - if(!torrentAttrs->createdBy.empty()) { - o << "Created By: " << torrentAttrs->createdBy << "\n"; - } - o << "Mode: " << torrentAttrs->mode << "\n"; - o << "Announce:" << "\n"; - for(std::vector<std::vector<std::string> >::const_iterator tierIter = - torrentAttrs->announceList.begin(), - eoi = torrentAttrs->announceList.end(); tierIter != eoi; ++tierIter) { - for(std::vector<std::string>::const_iterator i = (*tierIter).begin(), - eoi2 = (*tierIter).end(); i != eoi2; ++i) { - o << " " << *i; - } - o << "\n"; - } - o << "Info Hash: " - << util::toHex(torrentAttrs->infoHash) << "\n" - << "Piece Length: " - << util::abbrevSize(dctx->getPieceLength()) << "B\n" - << "The Number of Pieces: " - << dctx->getNumPieces() << "\n" - << "Total Length: " - << util::abbrevSize(dctx->getTotalLength()) << "B (" - << util::uitos(dctx->getTotalLength(), true) << ")\n"; - if(!torrentAttrs->urlList.empty()) { - o << "URL List: " << "\n"; - for(std::vector<std::string>::const_iterator i = - torrentAttrs->urlList.begin(), - eoi = torrentAttrs->urlList.end(); i != eoi; ++i) { - o << " " << *i << "\n"; - } - } - o << "Name: " << torrentAttrs->name << "\n" - << "Magnet URI: " << torrent2Magnet(torrentAttrs) << "\n"; - util::toStream - (dctx->getFileEntries().begin(), dctx->getFileEntries().end(), o); -} - void computeFastSet (std::vector<size_t>& fastSet, const std::string& ipaddr, size_t numPieces, const unsigned char* infoHash, size_t fastSetSize) diff --git a/src/bittorrent_helper.h b/src/bittorrent_helper.h index f9463a92..2757d33a 100644 --- a/src/bittorrent_helper.h +++ b/src/bittorrent_helper.h @@ -47,6 +47,9 @@ #include "a2netcompat.h" #include "Peer.h" #include "ValueBase.h" +#include "util.h" +#include "DownloadContext.h" +#include "TimeA2.h" namespace aria2 { @@ -142,9 +145,6 @@ void computeFastSet (std::vector<size_t>& fastSet, const std::string& ipaddr, size_t numPieces, const unsigned char* infoHash, size_t fastSetSize); -// Writes the detailed information about torrent loaded in dctx. -void print(std::ostream& o, const SharedHandle<DownloadContext>& dctx); - SharedHandle<TorrentAttribute> getTorrentAttrs (const SharedHandle<DownloadContext>& dctx); @@ -323,6 +323,55 @@ void extractPeer int getCompactLength(int family); +// Writes the detailed information about torrent loaded in dctx. +template<typename Output> +void print(Output& o, const SharedHandle<DownloadContext>& dctx) +{ + SharedHandle<TorrentAttribute> torrentAttrs = getTorrentAttrs(dctx); + o.write("*** BitTorrent File Information ***\n"); + if(!torrentAttrs->comment.empty()) { + o.printf("Comment: %s\n", torrentAttrs->comment.c_str()); + } + if(torrentAttrs->creationDate) { + o.printf("Creation Date: %s\n", + Time(torrentAttrs->creationDate).toHTTPDate().c_str()); + } + if(!torrentAttrs->createdBy.empty()) { + o.printf("Created By: %s\n", torrentAttrs->createdBy.c_str()); + } + o.printf("Mode: %s\n", torrentAttrs->mode.c_str()); + o.write("Announce:\n"); + for(std::vector<std::vector<std::string> >::const_iterator tierIter = + torrentAttrs->announceList.begin(), + eoi = torrentAttrs->announceList.end(); tierIter != eoi; ++tierIter) { + for(std::vector<std::string>::const_iterator i = (*tierIter).begin(), + eoi2 = (*tierIter).end(); i != eoi2; ++i) { + o.printf(" %s", (*i).c_str()); + } + o.write("\n"); + } + o.printf("Info Hash: %s\n", util::toHex(torrentAttrs->infoHash).c_str()); + o.printf("Piece Length: %sB\n", + util::abbrevSize(dctx->getPieceLength()).c_str()); + o.printf("The Number of Pieces: %lu\n", + static_cast<unsigned long>(dctx->getNumPieces())); + o.printf("Total Length: %sB (%s)\n", + util::abbrevSize(dctx->getTotalLength()).c_str(), + util::uitos(dctx->getTotalLength(), true).c_str()); + if(!torrentAttrs->urlList.empty()) { + o.write("URL List:\n"); + for(std::vector<std::string>::const_iterator i = + torrentAttrs->urlList.begin(), + eoi = torrentAttrs->urlList.end(); i != eoi; ++i) { + o.printf(" %s\n", (*i).c_str()); + } + } + o.printf("Name: %s\n", torrentAttrs->name.c_str()); + o.printf("Magnet URI: %s\n", torrent2Magnet(torrentAttrs).c_str()); + util::toStream + (dctx->getFileEntries().begin(), dctx->getFileEntries().end(), o); +} + } // namespace bittorrent } // namespace aria2 diff --git a/src/console.cc b/src/console.cc new file mode 100644 index 00000000..021d8dd4 --- /dev/null +++ b/src/console.cc @@ -0,0 +1,58 @@ +/* <!-- 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 "console.h" + +namespace aria2 { + +namespace global { + +#ifdef __MINGW32__ +SharedHandle<WinConsoleFile> cout; +#else // !__MINGW32__ +SharedHandle<BufferedFile> cout; +#endif // !__MINGW32__ + +void initConsole() +{ +#ifdef __MINGW32__ + cout.reset(new WinConsoleFile()); +#else // !__MINGW32__ + cout.reset(new BufferedFile(stdout)); +#endif // !__MINGW32__ +} + +} // namespace global + +} // namespace aria2 diff --git a/src/console.h b/src/console.h new file mode 100644 index 00000000..29f1b50e --- /dev/null +++ b/src/console.h @@ -0,0 +1,62 @@ +/* <!-- 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_CONSOLE_H +#define D_CONSOLE_H + +#include "common.h" +#include "SharedHandle.h" +#ifdef __MINGW32__ +# include "WinConsoleFile.h" +#else // !__MINGW32__ +# include "BufferedFile.h" +#endif // !__MINGW32__ + +namespace aria2 { + +namespace global { + +#ifdef __MINGW32__ +extern SharedHandle<WinConsoleFile> cout; +#else // !__MINGW32__ +extern SharedHandle<BufferedFile> cout; +#endif // !__MINGW32__ + +void initConsole(); + +} // namespace global + +} // namespace aria2 + +#endif // D_CONSOLE_H diff --git a/src/main.cc b/src/main.cc index 03f464f5..07f2ed60 100644 --- a/src/main.cc +++ b/src/main.cc @@ -38,10 +38,9 @@ #include <unistd.h> #include <getopt.h> -#include <fstream> -#include <iostream> #include <numeric> #include <vector> +#include <iostream> #include "SharedHandle.h" #include "LogFactory.h" @@ -69,6 +68,8 @@ #include "SocketCore.h" #include "DownloadContext.h" #include "fmt.h" +#include "NullOutputFile.h" +#include "console.h" #ifdef ENABLE_BITTORRENT # include "bittorrent_helper.h" #endif // ENABLE_BITTORRENT @@ -85,9 +86,6 @@ extern int optind, opterr, optopt; namespace aria2 { -// output stream to /dev/null -std::ofstream nullout(DEV_NULL); - SharedHandle<StatCalc> getStatCalc(const SharedHandle<Option>& op) { SharedHandle<StatCalc> statCalc; @@ -104,12 +102,12 @@ SharedHandle<StatCalc> getStatCalc(const SharedHandle<Option>& op) return statCalc; } -std::ostream& getSummaryOut(const SharedHandle<Option>& op) +SharedHandle<OutputFile> getSummaryOut(const SharedHandle<Option>& op) { if(op->getAsBool(PREF_QUIET)) { - return nullout; + return SharedHandle<OutputFile>(new NullOutputFile()); } else { - return std::cout; + return global::cout; } } @@ -120,7 +118,7 @@ void showTorrentFile(const std::string& uri) SharedHandle<Option> op(new Option()); SharedHandle<DownloadContext> dctx(new DownloadContext()); bittorrent::load(uri, dctx, op); - bittorrent::print(std::cout, dctx); + bittorrent::print(*global::cout, dctx); } } // namespace #endif // ENABLE_BITTORRENT @@ -135,8 +133,9 @@ void showMetalinkFile op->get(PREF_METALINK_BASE_URI)); std::vector<SharedHandle<FileEntry> > fileEntries; MetalinkEntry::toFileEntry(fileEntries, metalinkEntries); - util::toStream(fileEntries.begin(), fileEntries.end(), std::cout); - std::cout << std::endl; + util::toStream(fileEntries.begin(), fileEntries.end(), *global::cout); + global::cout->write("\n"); + global::cout->flush(); } } // namespace #endif // ENABLE_METALINK @@ -168,7 +167,7 @@ void showFiles printf("\n\n"); } } catch(RecoverableException& e) { - std::cout << e.stackTrace() << std::endl; + global::cout->printf("%s\n", e.stackTrace().c_str()); } } } @@ -269,7 +268,7 @@ error_code::Value main(int argc, char* argv[]) op->remove(PREF_SELECT_FILE); op->remove(PREF_PAUSE); if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty()) { - std::cout << MSG_NO_FILES_TO_DOWNLOAD << std::endl; + global::cout->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD); } else { exitStatus = MultiUrlRequestInfo(requestGroups, op, getStatCalc(op), getSummaryOut(op)).execute(); diff --git a/src/util.cc b/src/util.cc index c7b56bfa..7884474c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -97,95 +97,99 @@ namespace aria2 { #ifdef __MINGW32__ namespace { -int utf8ToWChar(wchar_t* out, size_t outLength, const std::string& src) +int utf8ToWChar(wchar_t* out, size_t outLength, const char* src) { - return MultiByteToWideChar(CP_UTF8, 0, src.c_str(), -1, - out, outLength); + return MultiByteToWideChar(CP_UTF8, 0, src, -1, out, outLength); } } // namespace namespace { -int ansiToWChar(wchar_t* out, size_t outLength, const std::string& src) +int ansiToWChar(wchar_t* out, size_t outLength, const char* src) { - return MultiByteToWideChar(CP_ACP, 0, src.c_str(), -1, - out, outLength); + return MultiByteToWideChar(CP_ACP, 0, src, -1, out, outLength); } } // namespace namespace { -int wCharToUtf8(char* out, size_t outLength, const std::wstring& src) +int wCharToUtf8(char* out, size_t outLength, const wchar_t* src) { - return WideCharToMultiByte(CP_UTF8, 0, src.c_str(), -1, - out, outLength, 0, 0); + return WideCharToMultiByte(CP_UTF8, 0, src, -1, out, outLength, 0, 0); } } // namespace namespace { -int wCharToAnsi(char* out, size_t outLength, const std::wstring& src) +int wCharToAnsi(char* out, size_t outLength, const wchar_t* src) { - return WideCharToMultiByte(CP_ACP, 0, src.c_str(), -1, - out, outLength, 0, 0); + return WideCharToMultiByte(CP_ACP, 0, src, -1, out, outLength, 0, 0); } } // namespace -std::wstring utf8ToWChar(const std::string& src) +std::wstring utf8ToWChar(const char* src) { int len = utf8ToWChar(0, 0, src); if(len == 0) { abort(); } - wchar_t* buf = new wchar_t[len]; + array_ptr<wchar_t> buf(new wchar_t[len]); len = utf8ToWChar(buf, len, src); if(len == 0) { abort(); } else { - return buf; + std::wstring dest(buf); + return dest; } } -std::string const std::string& src +std::wstring utf8ToWChar(const std::string& src) +{ + return utf8ToWChar(src.c_str()); +} + +std::string utf8ToNative(const std::string& src) { std::wstring wsrc = utf8ToWChar(src); - int len = wCharToAnsi(0, 0, wsrc); + int len = wCharToAnsi(0, 0, wsrc.c_str()); if(len == 0) { abort(); } - char* buf = new char[len]; - len = wCharToAnsi(buf, len, wsrc); + array_ptr<char> buf(new char[len]); + len = wCharToAnsi(buf, len, wsrc.c_str()); if(len == 0) { abort(); } else { - return buf; + std::string dest(buf); + return dest; } } std::string wCharToUtf8(const std::wstring& wsrc) { - int len = wCharToUtf8(0, 0, wsrc); + int len = wCharToUtf8(0, 0, wsrc.c_str()); if(len == 0) { abort(); } - char* buf = new char[len]; - len = wCharToUtf8(buf, len, wsrc); + array_ptr<char> buf(new char[len]); + len = wCharToUtf8(buf, len, wsrc.c_str()); if(len == 0) { abort(); } else { - return buf; + std::string dest(buf); + return dest; } } std::string nativeToUtf8(const std::string& src) { - int len = ansiToWChar(0, 0, src); + int len = ansiToWChar(0, 0, src.c_str()); if(len == 0) { abort(); } - wchar_t* buf = new wchar_t[len]; - len = ansiToWChar(buf, len, src); + array_ptr<wchar_t> buf(new wchar_t[len]); + len = ansiToWChar(buf, len, src.c_str()); if(len == 0) { abort(); } else { - return wCharToUtf8(buf); + return wCharToUtf8(std::wstring(buf)); } } #endif // __MINGW32__ @@ -89,6 +89,8 @@ inline uint64_t hton64(uint64_t x) { return byteswap64(x); } #ifdef __MINGW32__ std::wstring utf8ToWChar(const std::string& src); +std::wstring utf8ToWChar(const char* str); + std::string utf8ToNative(const std::string& src); std::string wCharToUtf8(const std::wstring& wsrc); @@ -261,20 +263,22 @@ int64_t getRealSize(const std::string& sizeWithUnit); std::string abbrevSize(int64_t size); -template<typename InputIterator> +template<typename InputIterator, typename Output> void toStream -(InputIterator first, InputIterator last, std::ostream& os) +(InputIterator first, InputIterator last, Output& os) { - os << _("Files:") << "\n"; - os << "idx|path/length" << "\n"; - os << "===+===========================================================================" << "\n"; + os.printf("%s\n" + "idx|path/length\n" + "===+===========================================================================\n", _("Files:")); int32_t count = 1; for(; first != last; ++first, ++count) { - os << std::setw(3) << count << "|" - << utf8ToNative((*first)->getPath()) << "\n"; - os << " |" << util::abbrevSize((*first)->getLength()) << "B (" - << util::uitos((*first)->getLength(), true) << ")\n"; - os << "---+---------------------------------------------------------------------------" << "\n"; + os.printf("%3d|%s\n" + " |%sB (%s)\n" + "---+---------------------------------------------------------------------------\n", + count, + (*first)->getPath().c_str(), + util::abbrevSize((*first)->getLength()).c_str(), + util::uitos((*first)->getLength(), true).c_str()); } } |
