summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2011-08-09 23:33:55 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2011-08-09 23:33:55 +0900
commita10cda2f17916895d8c6bc3cd69a360947017771 (patch)
tree0740833f77a3e239ea58e870a9dcb9086d43e516 /src
parent02307cee0a395d8405d0e160664d4a37c79fe16c (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.cc5
-rw-r--r--src/BufferedFile.h11
-rw-r--r--src/ConsoleStatCalc.cc44
-rw-r--r--src/FileEntry.h4
-rw-r--r--src/Logger.cc36
-rw-r--r--src/Logger.h7
-rw-r--r--src/Makefile.am9
-rw-r--r--src/MultiUrlRequestInfo.cc16
-rw-r--r--src/MultiUrlRequestInfo.h6
-rw-r--r--src/NullOutputFile.h52
-rw-r--r--src/OutputFile.h54
-rw-r--r--src/Platform.cc3
-rw-r--r--src/RequestGroupMan.cc36
-rw-r--r--src/RequestGroupMan.h10
-rw-r--r--src/WinConsoleFile.cc105
-rw-r--r--src/WinConsoleFile.h58
-rw-r--r--src/bittorrent_helper.cc48
-rw-r--r--src/bittorrent_helper.h55
-rw-r--r--src/console.cc58
-rw-r--r--src/console.h62
-rw-r--r--src/main.cc25
-rw-r--r--src/util.cc60
-rw-r--r--src/util.h24
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__
diff --git a/src/util.h b/src/util.h
index 049fa7a1..2f5d745b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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());
}
}