2007-11-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Preallocate non-requested file which is adjacent forward to 
requested
	file('requested' files means the files given in --select-file 
option)
	if they share a same piece.
	This fixes long pause in the file system which doesn't support 
sparse
	files like FAT32 while downloading.
	* src/MultiFileAllocationIterator.{h, cc}
	* test/MultiFileAllocationIteratorTest.cc
	* src/FileEntry.{h, cc}

	Removed unused _option.
	* src/MultiDiskAdaptor.h
	* test/MultiDiskAdaptorTest.cc
	* src/DefaultPieceStorage.cc

	Set the default value of --seed-ratio to 1.0.
	If 0.0 is given, then seeding continues regardless of share 
ratio.
	* src/version_usage.cc
	* src/option_processing.cc
	* src/BtSetup.cc
	* doc/aria2c.1.txt
	* doc/aria2c.1

	Fixed: Selective download is not working in BitTorrent
	* src/RequestGroup.cc

	Introduced Sequence class. Use this instead of 
Util::unfoldRange()
	* src/PieceStorage.h
	* test/MockPieceStorage.h
	* src/UnknownLengthPieceStorage.h
	* src/DefaultPieceStorage.{h, cc}
	* src/Metalink2RequestGroup.cc
	* src/RequestGroup.cc
	* src/Sequence.h
	* test/SequenceTest.cc
	* src/IntSequence.h
	* src/message.h
	* src/Util.{h, cc}
	* test/UtilTest.cc

	Added new function 'parse' to catch exception thrown by 
subclass's
	parseArg
	* src/OptionHandler.h
	* src/OptionParser.cc
	* src/NameMatchOptionHandler.h
	* src/OptionHandlerImpl.h
	* test/OptionHandlerTest.cc

	Added IntegerRangeOptionHandler. Used for --listen-port and
	--select-file. Now --listen-port accepts range of port.
	* src/OptionHandlerFactory.cc
	* src/version_usage.cc
	* src/OptionHandlerImpl.h
	* src/option_processing.cc
	* src/BtSetup.cc
	* src/PeerListenCommand.{h, cc}
	* doc/aria2c.1.txt
	* doc/aria2c.1
	
	Implemented operator< for Exception class to provide easy way to 
print
	exception stack trace.
	* src/Exception.{h, cc}
	* src/main.cc
	* src/option_processing.cc
pull/1/head
Tatsuhiro Tsujikawa 2007-11-21 16:14:40 +00:00
parent 59fb4066fb
commit c9e3d51054
46 changed files with 873 additions and 211 deletions

View File

@ -1,3 +1,69 @@
2007-11-20 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Preallocate non-requested file which is adjacent forward to requested
file('requested' files means the files given in --select-file option)
if they share a same piece.
This fixes long pause in the file system which doesn't support sparse
files like FAT32 while downloading.
* src/MultiFileAllocationIterator.{h, cc}
* test/MultiFileAllocationIteratorTest.cc
* src/FileEntry.{h, cc}
Removed unused _option.
* src/MultiDiskAdaptor.h
* test/MultiDiskAdaptorTest.cc
* src/DefaultPieceStorage.cc
Set the default value of --seed-ratio to 1.0.
If 0.0 is given, then seeding continues regardless of share ratio.
* src/version_usage.cc
* src/option_processing.cc
* src/BtSetup.cc
* doc/aria2c.1.txt
* doc/aria2c.1
Fixed: Selective download is not working in BitTorrent
* src/RequestGroup.cc
Introduced Sequence class. Use this instead of Util::unfoldRange()
* src/PieceStorage.h
* test/MockPieceStorage.h
* src/UnknownLengthPieceStorage.h
* src/DefaultPieceStorage.{h, cc}
* src/Metalink2RequestGroup.cc
* src/RequestGroup.cc
* src/Sequence.h
* test/SequenceTest.cc
* src/IntSequence.h
* src/message.h
* src/Util.{h, cc}
* test/UtilTest.cc
Added new function 'parse' to catch exception thrown by subclass's
parseArg
* src/OptionHandler.h
* src/OptionParser.cc
* src/NameMatchOptionHandler.h
* src/OptionHandlerImpl.h
* test/OptionHandlerTest.cc
Added IntegerRangeOptionHandler. Used for --listen-port and
--select-file. Now --listen-port accepts range of port.
* src/OptionHandlerFactory.cc
* src/version_usage.cc
* src/OptionHandlerImpl.h
* src/option_processing.cc
* src/BtSetup.cc
* src/PeerListenCommand.{h, cc}
* doc/aria2c.1.txt
* doc/aria2c.1
Implemented operator< for Exception class to provide easy way to print
exception stack trace.
* src/Exception.{h, cc}
* src/main.cc
* src/option_processing.cc
2007-11-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2007-11-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
* src/version_usage.cc * src/version_usage.cc

3
TODO
View File

@ -4,7 +4,6 @@
* Add SSL client cert support * Add SSL client cert support
* Better HTTP status handling * Better HTTP status handling
* Add the feature which adds or removes URLs on-the-fly. * Add the feature which adds or removes URLs on-the-fly.
* Add port range command-line option
* Add max peers command-line option * Add max peers command-line option
* Refacturing HttpConnection and FtpConnection * Refacturing HttpConnection and FtpConnection
* Query resource by location * Query resource by location
@ -57,3 +56,5 @@
-- remaining issues to be implemented for 0.12.0 release -- remaining issues to be implemented for 0.12.0 release
* Update translation * Update translation
* replace strtol with Util::parseInt
* precision of share ratio

View File

@ -1,11 +1,11 @@
.\" Title: aria2c .\" Title: aria2c
.\" Author: .\" Author:
.\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/> .\" Generator: DocBook XSL Stylesheets v1.73.1 <http://docbook.sf.net/>
.\" Date: 11/18/2007 .\" Date: 11/22/2007
.\" Manual: .\" Manual:
.\" Source: .\" Source:
.\" .\"
.TH "ARIA2C" "1" "11/18/2007" "" "" .TH "ARIA2C" "1" "11/22/2007" "" ""
.\" disable hyphenation .\" disable hyphenation
.nh .nh
.\" disable justification (adjust text to left margin only) .\" disable justification (adjust text to left margin only)
@ -319,6 +319,15 @@ to specify a range: "1\-5"\.
and and
\fI\-\fR \fI\-\fR
can be used together\. When used with the \-M option, index may vary depending on the query(see \-\-metalink\-* options)\. can be used together\. When used with the \-M option, index may vary depending on the query(see \-\-metalink\-* options)\.
.sp
.RS 4
.nf
Note: In multi file torrent, it seems that adjacent files specified
by this option are downloaded\. This is by design, not a bug\.
A single piece may include several files or part of files,
and aria2 writes the piece to the appropriate files\.
.fi
.RE
.RE .RE
.PP .PP
\-T, \-\-torrent\-file=TORRENT_FILE \-T, \-\-torrent\-file=TORRENT_FILE
@ -335,11 +344,18 @@ Set to false to prevent aria2 from entering BitTorrent mode even if the filename
.RS 4 .RS 4
Directly read from and write to each file mentioned in \.torrent file\. Default: Directly read from and write to each file mentioned in \.torrent file\. Default:
\fItrue\fR \fItrue\fR
.RE .sp
.PP
\-\-listen\-port=PORT
.RS 4 .RS 4
Set TCP port number for BitTorrent downloads\. Default: 6881\-6999 .nf
\-\-listen\-port=PORT\.\.\.
Set TCP port number for BitTorrent downloads\.
Multiple values can be specified by using \',\',
for example: "6881,6885"\.
You can also use \'\-\' to specify a range: "6881\-6999"\.
\',\' and \'\-\' can be used together\.
Default: 6881\-6999
.fi
.RE
.RE .RE
.PP .PP
\-\-max\-upload\-limit=SPEED \-\-max\-upload\-limit=SPEED
@ -360,7 +376,7 @@ Specify seeding time in minutes\. Also see the \-\-seed\-ratio option\.
.PP .PP
\-\-seed\-ratio=RATIO \-\-seed\-ratio=RATIO
.RS 4 .RS 4
Specify share ratio\. Seed completed torrents until share ratio reaches RATIO\. 1\.0 is encouraged\. If \-\-seed\-time option is specified along with this option, seeding ends when at least one of the conditions is satisfied\. Specify share ratio\. Seed completed torrents until share ratio reaches RATIO\. 1\.0 is encouraged\. Specify 0\.0 if you intend to do seeding regardless of share ratio\. If \-\-seed\-time option is specified along with this option, seeding ends when at least one of the conditions is satisfied\. Default: 1\.0
.RE .RE
.PP .PP
\-\-peer\-id\-prefix=PEERI_ID_PREFIX \-\-peer\-id\-prefix=PEERI_ID_PREFIX

View File

@ -229,14 +229,19 @@ http://host/image[000-100:2].img
and exit. and exit.
--select-file=INDEX...:: --select-file=INDEX...::
Set file to download by specifing its index. Set file to download by specifing its index.
You can find the file index using the You can find the file index using the
--show-files option. Multiple indexes can be --show-files option. Multiple indexes can be
specified by using ',', for example: "3,6". specified by using ',', for example: "3,6".
You can also use '-' to specify a range: "1-5". You can also use '-' to specify a range: "1-5".
',' and '-' can be used together. ',' and '-' can be used together.
When used with the -M option, index may vary When used with the -M option, index may vary
depending on the query(see --metalink-* options). depending on the query(see --metalink-* options).
Note: In multi file torrent, it seems that adjacent files specified
by this option are downloaded. This is by design, not a bug.
A single piece may include several files or part of files,
and aria2 writes the piece to the appropriate files.
-T, --torrent-file=TORRENT_FILE:: -T, --torrent-file=TORRENT_FILE::
The path to the .torrent file. The path to the .torrent file.
@ -252,9 +257,13 @@ http://host/image[000-100:2].img
mentioned in .torrent file. mentioned in .torrent file.
Default: 'true' Default: 'true'
--listen-port=PORT:: --listen-port=PORT...
Set TCP port number for BitTorrent downloads. Set TCP port number for BitTorrent downloads.
Default: 6881-6999 Multiple values can be specified by using ',',
for example: "6881,6885".
You can also use '-' to specify a range: "6881-6999".
',' and '-' can be used together.
Default: 6881-6999
--max-upload-limit=SPEED:: --max-upload-limit=SPEED::
Set max upload speed in bytes per sec. Set max upload speed in bytes per sec.
@ -267,11 +276,14 @@ http://host/image[000-100:2].img
--seed-ratio option. --seed-ratio option.
--seed-ratio=RATIO:: --seed-ratio=RATIO::
Specify share ratio. Seed completed torrents Specify share ratio. Seed completed torrents
until share ratio reaches RATIO. 1.0 is until share ratio reaches RATIO. 1.0 is
encouraged. If --seed-time option is specified encouraged. Specify 0.0 if you intend to do
along with this option, seeding ends when at seeding regardless of share ratio.
least one of the conditions is satisfied. If --seed-time option is specified along with
this option, seeding ends when at least one of
the conditions is satisfied.
Default: 1.0
--peer-id-prefix=PEERI_ID_PREFIX:: --peer-id-prefix=PEERI_ID_PREFIX::
Specify the prefix of peer ID. The peer ID in Specify the prefix of peer ID. The peer ID in

View File

@ -53,6 +53,7 @@
#include "LogFactory.h" #include "LogFactory.h"
#include "Logger.h" #include "Logger.h"
#include "Util.h" #include "Util.h"
#include "IntSequence.h"
BtSetup::BtSetup():_logger(LogFactory::getInstance()) {} BtSetup::BtSetup():_logger(LogFactory::getInstance()) {}
@ -85,9 +86,12 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
if(option->defined(PREF_SEED_TIME)) { if(option->defined(PREF_SEED_TIME)) {
unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60)); unionCri->addSeedCriteria(new TimeSeedCriteria(option->getAsInt(PREF_SEED_TIME)*60));
} }
if(option->defined(PREF_SEED_RATIO)) { {
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), btContext)); double ratio = option->getAsDouble(PREF_SEED_RATIO);
} if(ratio > 0.0) {
unionCri->addSeedCriteria(new ShareRatioSeedCriteria(option->getAsDouble(PREF_SEED_RATIO), btContext));
}
}
if(unionCri->getSeedCriterion().size() > 0) { if(unionCri->getSeedCriterion().size() > 0) {
commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(), commands.push_back(new SeedCheckCommand(CUIDCounterSingletonHolder::instance()->newID(),
requestGroup, requestGroup,
@ -98,13 +102,8 @@ Commands BtSetup::setup(RequestGroup* requestGroup,
if(PeerListenCommand::getNumInstance() == 0) { if(PeerListenCommand::getNumInstance() == 0) {
PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e); PeerListenCommand* listenCommand = PeerListenCommand::getInstance(e);
int32_t port; IntSequence seq = Util::parseIntRange(option->get(PREF_LISTEN_PORT));
int32_t listenPort = option->getAsInt(PREF_LISTEN_PORT); int32_t port = listenCommand->bindPort(seq);
if(listenPort == -1) {
port = listenCommand->bindPort(6881, 6999);
} else {
port = listenCommand->bindPort(listenPort, listenPort);
}
if(port == -1) { if(port == -1) {
_logger->error(_("Errors occurred while binding port.\n")); _logger->error(_("Errors occurred while binding port.\n"));
delete listenCommand; delete listenCommand;

View File

@ -33,11 +33,6 @@
*/ */
/* copyright --> */ /* copyright --> */
#include "DefaultDiskWriter.h" #include "DefaultDiskWriter.h"
#include "message.h"
#include "prefs.h"
#include "Util.h"
#include <errno.h>
#include <unistd.h>
DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter() {} DefaultDiskWriter::DefaultDiskWriter():AbstractDiskWriter() {}

View File

@ -391,8 +391,11 @@ void DefaultPieceStorage::setFileFilter(const Strings& filePaths)
bitfieldMan->enableFilter(); bitfieldMan->enableFilter();
} }
void DefaultPieceStorage::setFileFilter(const Integers& fileIndexes) void DefaultPieceStorage::setFileFilter(IntSequence seq)
{ {
Integers fileIndexes = seq.flush();
sort(fileIndexes.begin(), fileIndexes.end());
fileIndexes.erase(unique(fileIndexes.begin(), fileIndexes.end()), fileIndexes.end());
Strings filePaths; Strings filePaths;
const FileEntries& entries = diskAdaptor->getFileEntries(); const FileEntries& entries = diskAdaptor->getFileEntries();
for(int32_t i = 0; i < (int32_t)entries.size(); i++) { for(int32_t i = 0; i < (int32_t)entries.size(); i++) {
@ -441,7 +444,6 @@ void DefaultPieceStorage::initStorage()
MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor(); MultiDiskAdaptorHandle multiDiskAdaptor = new MultiDiskAdaptor();
multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength()); multiDiskAdaptor->setPieceLength(downloadContext->getPieceLength());
multiDiskAdaptor->setTopDir(downloadContext->getName()); multiDiskAdaptor->setTopDir(downloadContext->getName());
multiDiskAdaptor->setOption(option);
this->diskAdaptor = multiDiskAdaptor; this->diskAdaptor = multiDiskAdaptor;
} else { } else {
logger->debug("Instantiating CopyDiskAdaptor"); logger->debug("Instantiating CopyDiskAdaptor");
@ -456,11 +458,7 @@ void DefaultPieceStorage::initStorage()
this->diskAdaptor = copyDiskAdaptor; this->diskAdaptor = copyDiskAdaptor;
} }
} }
string storeDir = downloadContext->getDir();//option->get(PREF_DIR); diskAdaptor->setStoreDir(downloadContext->getDir());
// if(storeDir == "") {
// storeDir = ".";
// }
diskAdaptor->setStoreDir(storeDir);
diskAdaptor->setFileEntries(downloadContext->getFileEntries()); diskAdaptor->setFileEntries(downloadContext->getFileEntries());
} }

View File

@ -128,7 +128,7 @@ public:
virtual void setFileFilter(const Strings& filePaths); virtual void setFileFilter(const Strings& filePaths);
virtual void setFileFilter(const Integers& fileIndexes); virtual void setFileFilter(IntSequence seq);
virtual void clearFileFilter(); virtual void clearFileFilter();

View File

@ -47,9 +47,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <signal.h> #include <signal.h>
#include <algorithm>
volatile sig_atomic_t globalHaltRequested; volatile sig_atomic_t globalHaltRequested;

44
src/Exception.cc Normal file
View File

@ -0,0 +1,44 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 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 "Exception.h"
ostream& operator<<(ostream& o, const Exception& e)
{
o << e.getMsg() << "\n";
for(Exception* cause = e.getCause(); cause; cause = cause->getCause()) {
o << "Cause: " << cause->getMsg() << "\n";
}
return o;
}

View File

@ -63,6 +63,8 @@ public:
const string& getMsg() const { return msg; } const string& getMsg() const { return msg; }
Exception* getCause() const { return cause; } Exception* getCause() const { return cause; }
friend ostream& operator<<(ostream& o, const Exception& e);
}; };
#endif // _D_EXCEPTION_H_ #endif // _D_EXCEPTION_H_

View File

@ -62,3 +62,8 @@ FileEntry& FileEntry::operator=(const FileEntry& entry)
} }
return *this; return *this;
} }
bool FileEntry::operator<(const FileEntry& fileEntry) const
{
return offset < fileEntry.offset;
}

View File

@ -91,6 +91,8 @@ public:
{ {
return _uris; return _uris;
} }
bool operator<(const FileEntry& fileEntry) const;
}; };
typedef SharedHandle<FileEntry> FileEntryHandle; typedef SharedHandle<FileEntry> FileEntryHandle;

42
src/IntSequence.h Normal file
View File

@ -0,0 +1,42 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 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_INT_SEQUENCE_H_
#define _D_INT_SEQUENCE_H_
#include "Sequence.h"
typedef Sequence<int32_t> IntSequence;
#endif // _D_INT_SEQUENCE_H_

View File

@ -32,7 +32,7 @@ SRCS = Socket.h\
Request.cc Request.h\ Request.cc Request.h\
common.h\ common.h\
message.h\ message.h\
Exception.h\ Exception.cc Exception.h\
FatalException.h\ FatalException.h\
RecoverableException.h\ RecoverableException.h\
DlAbortEx.h\ DlAbortEx.h\

View File

@ -202,29 +202,29 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \ DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \
GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \ GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \ SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
message.h Exception.h FatalException.h RecoverableException.h \ message.h Exception.cc Exception.h FatalException.h \
DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \ RecoverableException.h DlAbortEx.h DlRetryEx.h Logger.h \
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ SimpleLogger.cc SimpleLogger.h TransferEncoding.h \
ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \
AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \
File.cc File.h Option.cc Option.h Base64.cc Base64.h \ DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \
CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \ Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \
HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ SharedHandle.h HandleRegistry.h FeatureConfig.cc \
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ FeatureConfig.h DownloadEngineFactory.cc \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \ DownloadEngineFactory.h RequestInfo.h SpeedCalc.cc SpeedCalc.h \
BitfieldMan.h BitfieldManFactory.cc BitfieldManFactory.h \ PeerStat.h BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \
Randomizer.h SimpleRandomizer.cc SimpleRandomizer.h \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \
FileAllocator.h HttpResponse.cc HttpResponse.h HttpRequest.cc \ SimpleRandomizer.h FileAllocator.h HttpResponse.cc \
HttpRequest.h Range.h AbstractProxyRequestCommand.cc \ HttpResponse.h HttpRequest.cc HttpRequest.h Range.h \
AbstractProxyRequestCommand.h AbstractProxyResponseCommand.cc \ AbstractProxyRequestCommand.cc AbstractProxyRequestCommand.h \
AbstractProxyResponseCommand.h Netrc.cc Netrc.h AuthConfig.cc \ AbstractProxyResponseCommand.cc AbstractProxyResponseCommand.h \
AuthConfig.h AuthResolver.h AbstractAuthResolver.h \ Netrc.cc Netrc.h AuthConfig.cc AuthConfig.h AuthResolver.h \
DefaultAuthResolver.cc DefaultAuthResolver.h \ AbstractAuthResolver.h DefaultAuthResolver.cc \
NetrcAuthResolver.cc NetrcAuthResolver.h AuthConfigFactory.cc \ DefaultAuthResolver.h NetrcAuthResolver.cc NetrcAuthResolver.h \
AuthConfigFactory.h OptionParser.cc OptionParser.h \ AuthConfigFactory.cc AuthConfigFactory.h OptionParser.cc \
OptionHandlerFactory.cc OptionHandlerFactory.h NameResolver.cc \ OptionParser.h OptionHandlerFactory.cc OptionHandlerFactory.h \
NameResolver.h RequestGroup.cc RequestGroup.h \ NameResolver.cc NameResolver.h RequestGroup.cc RequestGroup.h \
RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \ RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \
RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \ RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \
FileAllocationCommand.cc FileAllocationCommand.h \ FileAllocationCommand.cc FileAllocationCommand.h \
@ -433,7 +433,7 @@ am__objects_12 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
FtpTunnelResponseCommand.$(OBJEXT) SleepCommand.$(OBJEXT) \ FtpTunnelResponseCommand.$(OBJEXT) SleepCommand.$(OBJEXT) \
DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \ DownloadEngine.$(OBJEXT) GrowSegment.$(OBJEXT) \
PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \ PiecedSegment.$(OBJEXT) SegmentMan.$(OBJEXT) Util.$(OBJEXT) \
Request.$(OBJEXT) SimpleLogger.$(OBJEXT) \ Request.$(OBJEXT) Exception.$(OBJEXT) SimpleLogger.$(OBJEXT) \
ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \ ChunkedEncoding.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
DefaultDiskWriter.$(OBJEXT) File.$(OBJEXT) Option.$(OBJEXT) \ DefaultDiskWriter.$(OBJEXT) File.$(OBJEXT) Option.$(OBJEXT) \
Base64.$(OBJEXT) CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) \ Base64.$(OBJEXT) CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) \
@ -694,29 +694,29 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \ DownloadEngine.cc DownloadEngine.h Segment.h GrowSegment.cc \
GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \ GrowSegment.h PiecedSegment.cc PiecedSegment.h SegmentMan.cc \
SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \ SegmentMan.h Util.cc Util.h Request.cc Request.h common.h \
message.h Exception.h FatalException.h RecoverableException.h \ message.h Exception.cc Exception.h FatalException.h \
DlAbortEx.h DlRetryEx.h Logger.h SimpleLogger.cc \ RecoverableException.h DlAbortEx.h DlRetryEx.h Logger.h \
SimpleLogger.h TransferEncoding.h ChunkedEncoding.cc \ SimpleLogger.cc SimpleLogger.h TransferEncoding.h \
ChunkedEncoding.h DiskWriter.h AbstractDiskWriter.cc \ ChunkedEncoding.cc ChunkedEncoding.h DiskWriter.h \
AbstractDiskWriter.h DefaultDiskWriter.cc DefaultDiskWriter.h \ AbstractDiskWriter.cc AbstractDiskWriter.h \
File.cc File.h Option.cc Option.h Base64.cc Base64.h \ DefaultDiskWriter.cc DefaultDiskWriter.h File.cc File.h \
CookieBox.cc CookieBox.h LogFactory.cc LogFactory.h \ Option.cc Option.h Base64.cc Base64.h CookieBox.cc CookieBox.h \
NullLogger.h TimeA2.cc TimeA2.h SharedHandle.h \ LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \
HandleRegistry.h FeatureConfig.cc FeatureConfig.h \ SharedHandle.h HandleRegistry.h FeatureConfig.cc \
DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ FeatureConfig.h DownloadEngineFactory.cc \
SpeedCalc.cc SpeedCalc.h PeerStat.h BitfieldMan.cc \ DownloadEngineFactory.h RequestInfo.h SpeedCalc.cc SpeedCalc.h \
BitfieldMan.h BitfieldManFactory.cc BitfieldManFactory.h \ PeerStat.h BitfieldMan.cc BitfieldMan.h BitfieldManFactory.cc \
Randomizer.h SimpleRandomizer.cc SimpleRandomizer.h \ BitfieldManFactory.h Randomizer.h SimpleRandomizer.cc \
FileAllocator.h HttpResponse.cc HttpResponse.h HttpRequest.cc \ SimpleRandomizer.h FileAllocator.h HttpResponse.cc \
HttpRequest.h Range.h AbstractProxyRequestCommand.cc \ HttpResponse.h HttpRequest.cc HttpRequest.h Range.h \
AbstractProxyRequestCommand.h AbstractProxyResponseCommand.cc \ AbstractProxyRequestCommand.cc AbstractProxyRequestCommand.h \
AbstractProxyResponseCommand.h Netrc.cc Netrc.h AuthConfig.cc \ AbstractProxyResponseCommand.cc AbstractProxyResponseCommand.h \
AuthConfig.h AuthResolver.h AbstractAuthResolver.h \ Netrc.cc Netrc.h AuthConfig.cc AuthConfig.h AuthResolver.h \
DefaultAuthResolver.cc DefaultAuthResolver.h \ AbstractAuthResolver.h DefaultAuthResolver.cc \
NetrcAuthResolver.cc NetrcAuthResolver.h AuthConfigFactory.cc \ DefaultAuthResolver.h NetrcAuthResolver.cc NetrcAuthResolver.h \
AuthConfigFactory.h OptionParser.cc OptionParser.h \ AuthConfigFactory.cc AuthConfigFactory.h OptionParser.cc \
OptionHandlerFactory.cc OptionHandlerFactory.h NameResolver.cc \ OptionParser.h OptionHandlerFactory.cc OptionHandlerFactory.h \
NameResolver.h RequestGroup.cc RequestGroup.h \ NameResolver.cc NameResolver.h RequestGroup.cc RequestGroup.h \
RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \ RequestGroupAware.cc RequestGroupAware.h RequestGroupMan.cc \
RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \ RequestGroupMan.h FileAllocationMan.cc FileAllocationMan.h \
FileAllocationCommand.cc FileAllocationCommand.h \ FileAllocationCommand.cc FileAllocationCommand.h \
@ -925,6 +925,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Exception.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FileAllocationCommand.Po@am__quote@

View File

@ -101,9 +101,8 @@ RequestGroups Metalink2RequestGroup::generate(const string& metalinkFile)
_logger->notice(EX_NO_RESULT_WITH_YOUR_PREFS); _logger->notice(EX_NO_RESULT_WITH_YOUR_PREFS);
return RequestGroups(); return RequestGroups();
} }
Integers selectIndexes = Util::parseIntRange(_option->get(PREF_SELECT_FILE)).flush();
bool useIndex; bool useIndex;
Integers selectIndexes;
Util::unfoldRange(_option->get(PREF_SELECT_FILE), selectIndexes);
if(selectIndexes.size()) { if(selectIndexes.size()) {
useIndex = true; useIndex = true;
} else { } else {

View File

@ -36,7 +36,6 @@
#define _D_MULTI_DISK_ADAPTOR_H_ #define _D_MULTI_DISK_ADAPTOR_H_
#include "DiskAdaptor.h" #include "DiskAdaptor.h"
#include "Option.h"
#include "DiskWriter.h" #include "DiskWriter.h"
#include "File.h" #include "File.h"
@ -108,7 +107,6 @@ private:
string topDir; string topDir;
int32_t pieceLength; int32_t pieceLength;
DiskWriterEntries diskWriterEntries; DiskWriterEntries diskWriterEntries;
const Option* option;
void resetDiskWriterEntries(); void resetDiskWriterEntries();
@ -122,8 +120,7 @@ private:
string getTopDirPath() const; string getTopDirPath() const;
public: public:
MultiDiskAdaptor():pieceLength(0), MultiDiskAdaptor():pieceLength(0)
option(0)
{} {}
virtual ~MultiDiskAdaptor() {} virtual ~MultiDiskAdaptor() {}
@ -169,14 +166,6 @@ public:
int32_t getPieceLength() const { int32_t getPieceLength() const {
return pieceLength; return pieceLength;
} }
void setOption(const Option* option) {
this->option = option;
}
const Option* getOption() const {
return option;
}
}; };
typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle; typedef SharedHandle<MultiDiskAdaptor> MultiDiskAdaptorHandle;

View File

@ -40,7 +40,7 @@
MultiFileAllocationIterator::MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor): MultiFileAllocationIterator::MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor):
_diskAdaptor(diskAdaptor), _diskAdaptor(diskAdaptor),
_entries(diskAdaptor->getFileEntries()), _entries(makeFileEntries(diskAdaptor->getFileEntries(), diskAdaptor->getPieceLength())),
_currentEntry(0), _currentEntry(0),
_offset(0) _offset(0)
{} {}
@ -51,16 +51,14 @@ void MultiFileAllocationIterator::prepareNextEntry()
{ {
_currentEntry = 0; _currentEntry = 0;
_offset = 0; _offset = 0;
while(!_entries.empty()) { if(!_entries.empty()) {
FileEntryHandle entry = _entries.front(); FileEntryHandle entry = _entries.front();
_entries.pop_front(); _entries.pop_front();
if(entry->isRequested()) {
_currentEntry = entry; _currentEntry = entry;
_offset = File(_diskAdaptor->getStoreDir()+"/"+ _offset = File(_diskAdaptor->getStoreDir()+"/"+
_diskAdaptor->getTopDir()+"/"+ _diskAdaptor->getTopDir()+"/"+
_currentEntry->getPath()).size(); _currentEntry->getPath()).size();
break;
}
} }
} }
@ -99,3 +97,41 @@ int64_t MultiFileAllocationIterator::getTotalLength()
return _currentEntry->getLength(); return _currentEntry->getLength();
} }
} }
const FileEntries& MultiFileAllocationIterator::getFileEntries() const
{
return _entries;
}
FileEntries MultiFileAllocationIterator::makeFileEntries(const FileEntries& srcEntries, int32_t pieceLength) const
{
if(pieceLength == 0) {
FileEntries entries;
for(FileEntries::const_iterator itr = srcEntries.begin(); itr != srcEntries.end(); ++itr) {
if((*itr)->isRequested()) {
entries.push_back(*itr);
}
}
return entries;
}
FileEntries temp(srcEntries);
temp.push_front(new FileEntry());
FileEntries entries;
FileEntries::const_iterator done = temp.begin();
for(FileEntries::const_iterator itr = temp.begin()+1; itr != temp.end(); ++itr) {
if(!(*itr)->isRequested()) {
continue;
}
int64_t pieceStartOffset = ((*itr)->getOffset()/pieceLength)*pieceLength;
for(FileEntries::const_iterator i = itr-1; i != done; --i) {
if(pieceStartOffset < (*i)->getOffset()+(*i)->getLength()) {
entries.push_back(*i);
} else {
break;
}
}
entries.push_back(*itr);
done = itr;
}
return entries;
}

View File

@ -49,6 +49,8 @@ private:
FileEntries _entries; FileEntries _entries;
FileEntryHandle _currentEntry; FileEntryHandle _currentEntry;
int64_t _offset; int64_t _offset;
FileEntries makeFileEntries(const FileEntries& srcEntries, int32_t pieceLength) const;
public: public:
MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor); MultiFileAllocationIterator(MultiDiskAdaptor* diskAdaptor);
@ -66,6 +68,8 @@ public:
} }
virtual int64_t getTotalLength(); virtual int64_t getTotalLength();
const FileEntries& getFileEntries() const;
}; };
typedef SharedHandle<MultiFileAllocationIterator> MultiFileAllocationIteratorHandle; typedef SharedHandle<MultiFileAllocationIterator> MultiFileAllocationIteratorHandle;

View File

@ -36,10 +36,13 @@
#define _D_NAME_MATCH_OPTION_HANDLER_H_ #define _D_NAME_MATCH_OPTION_HANDLER_H_
#include "OptionHandler.h" #include "OptionHandler.h"
#include "DlAbortEx.h"
class NameMatchOptionHandler : public OptionHandler { class NameMatchOptionHandler : public OptionHandler {
protected: protected:
string _optName; string _optName;
virtual void parseArg(Option* option, const string& arg) = 0;
public: public:
NameMatchOptionHandler(const string& optName):_optName(optName) {} NameMatchOptionHandler(const string& optName):_optName(optName) {}
@ -49,6 +52,15 @@ public:
{ {
return strcasecmp(_optName.c_str(), optName.c_str()) == 0; return strcasecmp(_optName.c_str(), optName.c_str()) == 0;
} }
virtual void parse(Option* option, const string& arg)
{
try {
parseArg(option, arg);
} catch(Exception* e) {
throw new DlAbortEx(e, "Exception occurred while processing option %s", _optName.c_str());
}
}
}; };
typedef SharedHandle<NameMatchOptionHandler> NameMatchOptionHandlerHandle; typedef SharedHandle<NameMatchOptionHandler> NameMatchOptionHandlerHandle;

View File

@ -43,7 +43,7 @@ public:
virtual ~OptionHandler() {} virtual ~OptionHandler() {}
virtual bool canHandle(const string& optName) = 0; virtual bool canHandle(const string& optName) = 0;
virtual void parseArg(Option* option, const string& arg) = 0; virtual void parse(Option* option, const string& arg) = 0;
}; };
typedef SharedHandle<OptionHandler> OptionHandlerHandle; typedef SharedHandle<OptionHandler> OptionHandlerHandle;

View File

@ -55,11 +55,11 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
handlers.push_back(new UnitNumberOptionHandler(PREF_MIN_SEGMENT_SIZE, 1024)); handlers.push_back(new UnitNumberOptionHandler(PREF_MIN_SEGMENT_SIZE, 1024));
handlers.push_back(new ParameterOptionHandler(PREF_HTTP_PROXY_METHOD, handlers.push_back(new ParameterOptionHandler(PREF_HTTP_PROXY_METHOD,
V_GET, V_TUNNEL)); V_GET, V_TUNNEL));
handlers.push_back(new NumberOptionHandler(PREF_LISTEN_PORT, 1024, UINT16_MAX)); handlers.push_back(new IntegerRangeOptionHandler(PREF_LISTEN_PORT, 1024, UINT16_MAX));
handlers.push_back(new BooleanOptionHandler(PREF_FOLLOW_TORRENT)); handlers.push_back(new BooleanOptionHandler(PREF_FOLLOW_TORRENT));
handlers.push_back(new BooleanOptionHandler(PREF_NO_PREALLOCATION)); handlers.push_back(new BooleanOptionHandler(PREF_NO_PREALLOCATION));
handlers.push_back(new BooleanOptionHandler(PREF_DIRECT_FILE_MAPPING)); handlers.push_back(new BooleanOptionHandler(PREF_DIRECT_FILE_MAPPING));
handlers.push_back(new DefaultOptionHandler(PREF_SELECT_FILE)); handlers.push_back(new IntegerRangeOptionHandler(PREF_SELECT_FILE, 1, INT32_MAX));
handlers.push_back(new NumberOptionHandler(PREF_SEED_TIME, 0)); handlers.push_back(new NumberOptionHandler(PREF_SEED_TIME, 0));
handlers.push_back(new FloatNumberOptionHandler(PREF_SEED_RATIO, 0.0)); handlers.push_back(new FloatNumberOptionHandler(PREF_SEED_RATIO, 0.0));
handlers.push_back(new UnitNumberOptionHandler(PREF_MAX_UPLOAD_LIMIT, 0)); handlers.push_back(new UnitNumberOptionHandler(PREF_MAX_UPLOAD_LIMIT, 0));

View File

@ -38,6 +38,7 @@
#include "OptionHandler.h" #include "OptionHandler.h"
#include "NameMatchOptionHandler.h" #include "NameMatchOptionHandler.h"
#include "Util.h" #include "Util.h"
#include "DlAbortEx.h"
#include "FatalException.h" #include "FatalException.h"
#include "prefs.h" #include "prefs.h"
@ -47,7 +48,7 @@ public:
virtual bool canHandle(const string& optName) { return true; } virtual bool canHandle(const string& optName) { return true; }
virtual void parseArg(Option* option, const string& arg) {} virtual void parse(Option* option, const string& arg) {}
}; };
class BooleanOptionHandler : public NameMatchOptionHandler { class BooleanOptionHandler : public NameMatchOptionHandler {
@ -68,6 +69,29 @@ public:
} }
}; };
class IntegerRangeOptionHandler : public NameMatchOptionHandler {
private:
int32_t _min;
int32_t _max;
public:
IntegerRangeOptionHandler(const string& optName, int32_t min, int32_t max):NameMatchOptionHandler(optName), _min(min), _max(max) {}
virtual ~IntegerRangeOptionHandler() {}
virtual void parseArg(Option* option, const string& optarg)
{
IntSequence seq = Util::parseIntRange(optarg);
while(seq.hasNext()) {
int32_t v = seq.next();
if(v < _min || _max < v) {
string msg = _optName+" "+_("must be between %s and %s.");
throw new DlAbortEx(msg.c_str(), Util::llitos(_min).c_str(), Util::llitos(_max).c_str());
}
option->put(_optName, optarg);
}
}
};
class NumberOptionHandler : public NameMatchOptionHandler { class NumberOptionHandler : public NameMatchOptionHandler {
private: private:
int64_t _min; int64_t _min;
@ -79,7 +103,7 @@ public:
virtual void parseArg(Option* option, const string& optarg) virtual void parseArg(Option* option, const string& optarg)
{ {
int64_t num = strtoll(optarg.c_str(), 0, 10); int64_t num = Util::parseLLInt(optarg);
parseArg(option, num); parseArg(option, num);
} }
@ -217,7 +241,7 @@ public:
virtual void parseArg(Option* option, const string& optarg) virtual void parseArg(Option* option, const string& optarg)
{ {
pair<string, string> proxy = Util::split(optarg, ":"); pair<string, string> proxy = Util::split(optarg, ":");
int32_t port = strtol(proxy.second.c_str(), 0, 10); int32_t port = Util::parseInt(proxy.second);
if(proxy.first.empty() || proxy.second.empty() || if(proxy.first.empty() || proxy.second.empty() ||
port <= 0 || 65535 < port) { port <= 0 || 65535 < port) {
throw new FatalException(_("unrecognized proxy format")); throw new FatalException(_("unrecognized proxy format"));

View File

@ -47,7 +47,7 @@ void OptionParser::parse(Option* option, istream& is)
} }
pair<string, string> nv = Util::split(line, "="); pair<string, string> nv = Util::split(line, "=");
OptionHandlerHandle handler = getOptionHandlerByName(nv.first); OptionHandlerHandle handler = getOptionHandlerByName(nv.first);
handler->parseArg(option, nv.second); handler->parse(option, nv.second);
} }
} }

View File

@ -58,13 +58,10 @@ PeerListenCommand::~PeerListenCommand()
--__numInstance; --__numInstance;
} }
int32_t PeerListenCommand::bindPort(int32_t portRangeStart, int32_t PeerListenCommand::bindPort(IntSequence& seq)
int32_t portRangeEnd)
{ {
if(portRangeStart > portRangeEnd) { while(seq.hasNext()) {
return -1; int32_t port = seq.next();
}
for(int32_t port = portRangeStart; port <= portRangeEnd; port++) {
try { try {
socket->beginListen(port); socket->beginListen(port);
logger->info(MSG_LISTENING_PORT, logger->info(MSG_LISTENING_PORT,

View File

@ -37,6 +37,7 @@
#include "Command.h" #include "Command.h"
#include "Socket.h" #include "Socket.h"
#include "IntSequence.h"
class DownloadEngine; class DownloadEngine;
@ -57,7 +58,7 @@ public:
virtual bool execute(); virtual bool execute();
int32_t bindPort(int32_t portRangeStart, int32_t portRangeEnd); int32_t bindPort(IntSequence& seq);
void setLowestSpeedLimit(int32_t speed) void setLowestSpeedLimit(int32_t speed)
{ {

View File

@ -37,6 +37,7 @@
#include "common.h" #include "common.h"
#include "TimeA2.h" #include "TimeA2.h"
#include "IntSequence.h"
class Piece; class Piece;
extern typedef SharedHandle<Piece> PieceHandle; extern typedef SharedHandle<Piece> PieceHandle;
@ -124,7 +125,7 @@ public:
virtual void setFileFilter(const Strings& filePaths) = 0; virtual void setFileFilter(const Strings& filePaths) = 0;
virtual void setFileFilter(const Integers& fileIndexes) = 0; virtual void setFileFilter(IntSequence seq) = 0;
virtual void clearFileFilter() = 0; virtual void clearFileFilter() = 0;

View File

@ -73,7 +73,6 @@
#ifdef ENABLE_METALINK #ifdef ENABLE_METALINK
# include "MetalinkPostDownloadHandler.h" # include "MetalinkPostDownloadHandler.h"
#endif // ENABLE_METALINK #endif // ENABLE_METALINK
#include <cerrno>
int32_t RequestGroup::_gidCounter = 0; int32_t RequestGroup::_gidCounter = 0;
@ -148,15 +147,16 @@ Commands RequestGroup::createInitialCommand(DownloadEngine* e)
throw new DownloadFailureException(EX_DUPLICATE_FILE_DOWNLOAD, throw new DownloadFailureException(EX_DUPLICATE_FILE_DOWNLOAD,
getFilePath().c_str()); getFilePath().c_str());
} }
initPieceStorage();
if(btContext->getFileEntries().size() > 1) { if(btContext->getFileEntries().size() > 1) {
// this is really multi file torrent. // this is really multi file torrent.
// clear http/ftp uris because the current implementation does not // clear http/ftp uris because the current implementation does not
// allow integrating multi-file torrent and http/ftp. // allow integrating multi-file torrent and http/ftp.
_logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp."); _logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp.");
_uris.clear(); _uris.clear();
}
initPieceStorage(); _pieceStorage->setFileFilter(Util::parseIntRange(_option->get(PREF_SELECT_FILE)));
}
BtProgressInfoFileHandle progressInfoFile = BtProgressInfoFileHandle progressInfoFile =
new DefaultBtProgressInfoFile(_downloadContext, new DefaultBtProgressInfoFile(_downloadContext,

View File

@ -48,7 +48,6 @@
#include "DownloadContext.h" #include "DownloadContext.h"
#include "Piece.h" #include "Piece.h"
#include "a2io.h" #include "a2io.h"
#include <errno.h>
SegmentEntry::SegmentEntry(int32_t cuid, const SegmentHandle& segment): SegmentEntry::SegmentEntry(int32_t cuid, const SegmentHandle& segment):
cuid(cuid), segment(segment) {} cuid(cuid), segment(segment) {}

99
src/Sequence.h Normal file
View File

@ -0,0 +1,99 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2006 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_SEQUENCE_H_
#define _D_SEQUENCE_H_
#include <deque>
using namespace std;
template<typename T>
class Sequence
{
public:
// Generates value in [_first, _last). _last is not included.
class Value {
private:
T _first;
T _last;
public:
Value(const T& first, const T& last):_first(first), _last(last) {}
T next()
{
return _first++;
}
bool hasNext() const
{
return _first != _last;
}
};
typedef deque<Value> Values;
private:
Values _values;
public:
Sequence(const Values& values):
_values(values) {}
T next()
{
if(_values.empty()) {
return T();
}
T t = _values.front().next();
if(!_values.front().hasNext()) {
_values.pop_front();
}
return t;
}
bool hasNext()
{
return !_values.empty();
}
deque<T> flush()
{
deque<T> r;
while(hasNext()) {
r.push_back(next());
}
return r;
}
};
#endif // _D_SEQUENCE_H_

View File

@ -154,7 +154,7 @@ public:
virtual void setFileFilter(const Strings& filePaths) {} virtual void setFileFilter(const Strings& filePaths) {}
virtual void setFileFilter(const Integers& fileIndexes) {} virtual void setFileFilter(IntSequence seq) {}
virtual void clearFileFilter() {} virtual void clearFileFilter() {}

View File

@ -464,6 +464,58 @@ void Util::unfoldRange(const string& src, Integers& range) {
range.erase(unique(range.begin(), range.end()), range.end()); range.erase(unique(range.begin(), range.end()), range.end());
} }
int32_t Util::parseInt(const string& s, int32_t base)
{
char* stop;
errno = 0;
long int v = strtol(s.c_str(), &stop, base);
if(*stop != '\0') {
throw new DlAbortEx(MSG_ILLEGAL_CHARACTER, stop);
} else if((v == LONG_MIN || v == LONG_MAX) && errno == ERANGE || v > INT32_MAX || v < INT32_MIN) {
throw new DlAbortEx(MSG_OVERFLOW_UNDERFLOW_DETECTED, s.c_str());
}
return v;
}
int64_t Util::parseLLInt(const string& s, int32_t base)
{
char* stop;
errno = 0;
int64_t v = strtoll(s.c_str(), &stop, base);
if(*stop != '\0') {
throw new DlAbortEx(MSG_ILLEGAL_CHARACTER, stop);
} else if((v == INT64_MIN || v == INT64_MAX) && errno == ERANGE) {
throw new DlAbortEx(MSG_OVERFLOW_UNDERFLOW_DETECTED, s.c_str());
}
return v;
}
IntSequence Util::parseIntRange(const string& src)
{
IntSequence::Values values;
string temp = src;
while(temp.size()) {
pair<string, string> p = Util::split(temp, ",");
temp = p.second;
if(p.first.empty()) {
continue;
}
if(p.first.find("-") == string::npos) {
int32_t v = Util::parseInt(p.first.c_str());
values.push_back(IntSequence::Value(v, v+1));
} else {
pair<string, string> vp = Util::split(p.first.c_str(), "-");
if(vp.first.empty() || vp.second.empty()) {
throw new DlAbortEx(MSG_INCOMPLETE_RANGE, p.first.c_str());
}
int32_t v1 = Util::parseInt(vp.first.c_str());
int32_t v2 = Util::parseInt(vp.second.c_str());
values.push_back(IntSequence::Value(v1, v2+1));
}
}
return values;
}
string Util::getContentDispositionFilename(const string& header) { string Util::getContentDispositionFilename(const string& header) {
string keyName = "filename="; string keyName = "filename=";
string::size_type attributesp = header.find(keyName); string::size_type attributesp = header.find(keyName);

View File

@ -38,6 +38,7 @@
#include "common.h" #include "common.h"
#include "a2time.h" #include "a2time.h"
#include "FileEntry.h" #include "FileEntry.h"
#include "IntSequence.h"
#include <utility> #include <utility>
#include <deque> #include <deque>
#include <ostream> #include <ostream>
@ -112,6 +113,12 @@ public:
static void unfoldRange(const string& src, Integers& range); static void unfoldRange(const string& src, Integers& range);
static int32_t parseInt(const string& s, int32_t base = 10);
static int64_t parseLLInt(const string& s, int32_t base = 10);
static IntSequence parseIntRange(const string& src);
// this function temporarily put here // this function temporarily put here
static string getContentDispositionFilename(const string& header); static string getContentDispositionFilename(const string& header);

View File

@ -319,7 +319,7 @@ int main(int argc, char* argv[]) {
downloadUri(op, args); downloadUri(op, args);
} }
} catch(Exception* ex) { } catch(Exception* ex) {
cerr << EX_EXCEPTION_CAUGHT << "\n" << ex->getMsg() << endl; cerr << EX_EXCEPTION_CAUGHT << "\n" << *ex << endl;
delete ex; delete ex;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -126,6 +126,9 @@
#define MSG_DAEMON_FAILED _("daemon failed.") #define MSG_DAEMON_FAILED _("daemon failed.")
#define MSG_VERIFICATION_SUCCESSFUL _("Verification finished successfully. file=%s") #define MSG_VERIFICATION_SUCCESSFUL _("Verification finished successfully. file=%s")
#define MSG_VERIFICATION_FAILED _("Checksum error detected. file=%s") #define MSG_VERIFICATION_FAILED _("Checksum error detected. file=%s")
#define MSG_ILLEGAL_CHARACTER _("Illegal character detected: %s")
#define MSG_INCOMPLETE_RANGE _("Incomplete range specified. %s")
#define MSG_OVERFLOW_UNDERFLOW_DETECTED _("Overflow/underflow detected: %s")
#define EX_TIME_OUT _("Timeout.") #define EX_TIME_OUT _("Timeout.")
#define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.") #define EX_INVALID_CHUNK_SIZE _("Invalid chunk size.")

View File

@ -71,7 +71,7 @@ Option* option_processing(int argc, char* const argv[])
op->put(PREF_SPLIT, "1"); op->put(PREF_SPLIT, "1");
op->put(PREF_DAEMON, V_FALSE); op->put(PREF_DAEMON, V_FALSE);
op->put(PREF_SEGMENT_SIZE, Util::itos((int32_t)(1024*1024))); op->put(PREF_SEGMENT_SIZE, Util::itos((int32_t)(1024*1024)));
op->put(PREF_LISTEN_PORT, "-1"); op->put(PREF_LISTEN_PORT, "6881-6999");
op->put(PREF_METALINK_SERVERS, "5"); op->put(PREF_METALINK_SERVERS, "5");
op->put(PREF_FOLLOW_TORRENT, op->put(PREF_FOLLOW_TORRENT,
#ifdef ENABLE_BITTORRENT #ifdef ENABLE_BITTORRENT
@ -124,6 +124,7 @@ Option* option_processing(int argc, char* const argv[])
op->put(PREF_ENABLE_HTTP_KEEP_ALIVE, V_FALSE); op->put(PREF_ENABLE_HTTP_KEEP_ALIVE, V_FALSE);
op->put(PREF_ENABLE_HTTP_PIPELINING, V_FALSE); op->put(PREF_ENABLE_HTTP_PIPELINING, V_FALSE);
op->put(PREF_MAX_HTTP_PIPELINING, "2"); op->put(PREF_MAX_HTTP_PIPELINING, "2");
op->put(PREF_SEED_RATIO, "1.0");
while(1) { while(1) {
int optIndex = 0; int optIndex = 0;
int lopt; int lopt;
@ -407,14 +408,14 @@ Option* option_processing(int argc, char* const argv[])
oparser.parse(op, cfstream); oparser.parse(op, cfstream);
} catch(Exception* e) { } catch(Exception* e) {
cerr << "Parse error in " << cfname << endl; cerr << "Parse error in " << cfname << endl;
cerr << e->getMsg() << endl; cerr << *e << endl;
delete e; delete e;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
try { try {
oparser.parse(op, cmdstream); oparser.parse(op, cmdstream);
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << *e << endl;
delete e; delete e;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -242,7 +242,11 @@ void showUsage() {
cout << _(" --direct-file-mapping=true|false Directly read from and write to each file\n" cout << _(" --direct-file-mapping=true|false Directly read from and write to each file\n"
" mentioned in .torrent file.\n" " mentioned in .torrent file.\n"
" Default: true") << endl; " Default: true") << endl;
cout << _(" --listen-port=PORT Set TCP port number for BitTorrent downloads.\n" cout << _(" --listen-port=PORT... Set TCP port number for BitTorrent downloads.\n"
" Multiple values can be specified by using ',',\n"
" for example: \"6881,6885\".\n"
" You can also use '-' to specify a range: \"6881-6999\".\n"
" ',' and '-' can be used together.\n"
" Default: 6881-6999") << endl; " Default: 6881-6999") << endl;
cout << _(" --max-upload-limit=SPEED Set max upload speed in bytes per sec.\n" cout << _(" --max-upload-limit=SPEED Set max upload speed in bytes per sec.\n"
" 0 means unrestricted.\n" " 0 means unrestricted.\n"
@ -252,9 +256,12 @@ void showUsage() {
" --seed-ratio option.") << endl; " --seed-ratio option.") << endl;
cout << _(" --seed-ratio=RATIO Specify share ratio. Seed completed torrents\n" cout << _(" --seed-ratio=RATIO Specify share ratio. Seed completed torrents\n"
" until share ratio reaches RATIO. 1.0 is\n" " until share ratio reaches RATIO. 1.0 is\n"
" encouraged. If --seed-time option is specified\n" " encouraged. Specify 0.0 if you intend to do\n"
" along with this option, seeding ends when at\n" " seeding regardless of share ratio.\n"
" least one of the conditions is satisfied.") << endl; " If --seed-time option is specified along with\n"
" this option, seeding ends when at least one of\n"
" the conditions is satisfied.\n"
" Default: 1.0") << endl;
cout << _(" --peer-id-prefix=PEERI_ID_PREFIX Specify the prefix of peer ID. The peer ID in\n" cout << _(" --peer-id-prefix=PEERI_ID_PREFIX Specify the prefix of peer ID. The peer ID in\n"
" in BitTorrent is 20 byte length. If more than 20\n" " in BitTorrent is 20 byte length. If more than 20\n"
" bytes are specified, only first 20\n" " bytes are specified, only first 20\n"

View File

@ -1,6 +1,7 @@
TESTS = aria2c TESTS = aria2c
check_PROGRAMS = $(TESTS) check_PROGRAMS = $(TESTS)
aria2c_SOURCES = AllTest.cc\ aria2c_SOURCES = AllTest.cc\
SequenceTest.cc\
a2functionalTest.cc\ a2functionalTest.cc\
FileEntryTest.cc\ FileEntryTest.cc\
PieceTest.cc\ PieceTest.cc\

View File

@ -112,9 +112,10 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES = CONFIG_CLEAN_FILES =
am__EXEEXT_1 = aria2c$(EXEEXT) am__EXEEXT_1 = aria2c$(EXEEXT)
am__aria2c_SOURCES_DIST = AllTest.cc a2functionalTest.cc \ am__aria2c_SOURCES_DIST = AllTest.cc SequenceTest.cc \
FileEntryTest.cc PieceTest.cc SegmentTest.cc \ a2functionalTest.cc FileEntryTest.cc PieceTest.cc \
GrowSegmentTest.cc SingleFileAllocationIteratorTest.cc \ SegmentTest.cc GrowSegmentTest.cc \
SingleFileAllocationIteratorTest.cc \
DefaultBtProgressInfoFileTest.cc \ DefaultBtProgressInfoFileTest.cc \
SingleFileDownloadContextTest.cc RequestGroupTest.cc \ SingleFileDownloadContextTest.cc RequestGroupTest.cc \
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \ PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
@ -204,9 +205,10 @@ am__aria2c_SOURCES_DIST = AllTest.cc a2functionalTest.cc \
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkPostDownloadHandlerTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT) @ENABLE_METALINK_TRUE@ MetalinkHelperTest.$(OBJEXT)
am_aria2c_OBJECTS = AllTest.$(OBJEXT) a2functionalTest.$(OBJEXT) \ am_aria2c_OBJECTS = AllTest.$(OBJEXT) SequenceTest.$(OBJEXT) \
FileEntryTest.$(OBJEXT) PieceTest.$(OBJEXT) \ a2functionalTest.$(OBJEXT) FileEntryTest.$(OBJEXT) \
SegmentTest.$(OBJEXT) GrowSegmentTest.$(OBJEXT) \ PieceTest.$(OBJEXT) SegmentTest.$(OBJEXT) \
GrowSegmentTest.$(OBJEXT) \
SingleFileAllocationIteratorTest.$(OBJEXT) \ SingleFileAllocationIteratorTest.$(OBJEXT) \
DefaultBtProgressInfoFileTest.$(OBJEXT) \ DefaultBtProgressInfoFileTest.$(OBJEXT) \
SingleFileDownloadContextTest.$(OBJEXT) \ SingleFileDownloadContextTest.$(OBJEXT) \
@ -416,9 +418,9 @@ target_cpu = @target_cpu@
target_os = @target_os@ target_os = @target_os@
target_vendor = @target_vendor@ target_vendor = @target_vendor@
TESTS = aria2c TESTS = aria2c
aria2c_SOURCES = AllTest.cc a2functionalTest.cc FileEntryTest.cc \ aria2c_SOURCES = AllTest.cc SequenceTest.cc a2functionalTest.cc \
PieceTest.cc SegmentTest.cc GrowSegmentTest.cc \ FileEntryTest.cc PieceTest.cc SegmentTest.cc \
SingleFileAllocationIteratorTest.cc \ GrowSegmentTest.cc SingleFileAllocationIteratorTest.cc \
DefaultBtProgressInfoFileTest.cc \ DefaultBtProgressInfoFileTest.cc \
SingleFileDownloadContextTest.cc RequestGroupTest.cc \ SingleFileDownloadContextTest.cc RequestGroupTest.cc \
PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \ PStringBuildVisitorTest.cc ParameterizedStringParserTest.cc \
@ -577,6 +579,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentManTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentManTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SequenceTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShareRatioSeedCriteriaTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShareRatioSeedCriteriaTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SharedHandleTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SharedHandleTest.Po@am__quote@

View File

@ -109,7 +109,7 @@ public:
virtual void setFileFilter(const Strings& filePaths) {} virtual void setFileFilter(const Strings& filePaths) {}
virtual void setFileFilter(const Integers& fileIndexes) {} virtual void setFileFilter(IntSequence seq) {}
virtual void clearFileFilter() {} virtual void clearFileFilter() {}

View File

@ -11,18 +11,13 @@ class MultiDiskAdaptorTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testReadData); CPPUNIT_TEST(testReadData);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
Option* option;
MultiDiskAdaptorHandle adaptor; MultiDiskAdaptorHandle adaptor;
public: public:
MultiDiskAdaptorTest():option(0), adaptor(0) {} MultiDiskAdaptorTest():adaptor(0) {}
void setUp() { void setUp() {
delete option;
option = new Option();
adaptor = new MultiDiskAdaptor(); adaptor = new MultiDiskAdaptor();
adaptor->setPieceLength(2); adaptor->setPieceLength(2);
adaptor->setOption(new Option());
adaptor->setStoreDir("."); adaptor->setStoreDir(".");
adaptor->setTopDir("."); adaptor->setTopDir(".");
} }

View File

@ -7,6 +7,7 @@ class MultiFileAllocationIteratorTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(MultiFileAllocationIteratorTest); CPPUNIT_TEST_SUITE(MultiFileAllocationIteratorTest);
CPPUNIT_TEST(testAllocate); CPPUNIT_TEST(testAllocate);
CPPUNIT_TEST(testMakeFileEntries);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
@ -14,11 +15,54 @@ public:
void setUp() {} void setUp() {}
void testAllocate(); void testAllocate();
void testMakeFileEntries();
}; };
CPPUNIT_TEST_SUITE_REGISTRATION( MultiFileAllocationIteratorTest ); CPPUNIT_TEST_SUITE_REGISTRATION( MultiFileAllocationIteratorTest );
void MultiFileAllocationIteratorTest::testMakeFileEntries()
{
FileEntryHandle fs[] = {
new FileEntry("file1", 1536, 0),
new FileEntry("file2", 2048, 1536),
new FileEntry("file3", 1024, 3584),
new FileEntry("file4", 1024, 4608),
new FileEntry("file5", 1024, 5632),
new FileEntry("file6", 1024, 6656),
new FileEntry("file7", 256, 7680),
new FileEntry("file8", 768, 7936),
new FileEntry("file9", 256, 8704),
new FileEntry("fileA", 256, 8960),
};
fs[1]->setRequested(false);
fs[3]->setRequested(false);
fs[4]->setRequested(false);
fs[5]->setRequested(false);
fs[6]->setRequested(false);
fs[8]->setRequested(false);
fs[9]->setRequested(false);
MultiDiskAdaptorHandle diskAdaptor = new MultiDiskAdaptor();
diskAdaptor->setFileEntries(FileEntries(&fs[0], &fs[10]));
diskAdaptor->setPieceLength(1024);
MultiFileAllocationIteratorHandle itr = diskAdaptor->fileAllocationIterator();
FileEntries entries = itr->getFileEntries();
sort(entries.begin(), entries.end());
CPPUNIT_ASSERT_EQUAL((size_t)6, entries.size());
CPPUNIT_ASSERT_EQUAL(string("file1"), entries[0]->getPath());
CPPUNIT_ASSERT_EQUAL(string("file2"), entries[1]->getPath());
CPPUNIT_ASSERT_EQUAL(string("file3"), entries[2]->getPath());
CPPUNIT_ASSERT_EQUAL(string("file6"), entries[3]->getPath());
CPPUNIT_ASSERT_EQUAL(string("file7"), entries[4]->getPath());
CPPUNIT_ASSERT_EQUAL(string("file8"), entries[5]->getPath());
}
void MultiFileAllocationIteratorTest::testAllocate() void MultiFileAllocationIteratorTest::testAllocate()
{ {
string dir = "/tmp"; string dir = "/tmp";

View File

@ -52,7 +52,7 @@ void OptionHandlerTest::testNullOptionHandler()
{ {
NullOptionHandler handler; NullOptionHandler handler;
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
handler.parseArg(0, "bar"); handler.parse(0, "bar");
} }
void OptionHandlerTest::testBooleanOptionHandler() void OptionHandlerTest::testBooleanOptionHandler()
@ -61,12 +61,12 @@ void OptionHandlerTest::testBooleanOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, V_TRUE); handler.parse(&option, V_TRUE);
CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get("foo"));
handler.parseArg(&option, V_FALSE); handler.parse(&option, V_FALSE);
CPPUNIT_ASSERT_EQUAL(string(V_FALSE), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string(V_FALSE), option.get("foo"));
try { try {
handler.parseArg(&option, "hello"); handler.parse(&option, "hello");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -80,7 +80,7 @@ void OptionHandlerTest::testNumberOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "0"); handler.parse(&option, "0");
CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo"));
} }
@ -88,10 +88,10 @@ void OptionHandlerTest::testNumberOptionHandler_min()
{ {
NumberOptionHandler handler("foo", 1); NumberOptionHandler handler("foo", 1);
Option option; Option option;
handler.parseArg(&option, "1"); handler.parse(&option, "1");
CPPUNIT_ASSERT_EQUAL(string("1"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("1"), option.get("foo"));
try { try {
handler.parseArg(&option, "0"); handler.parse(&option, "0");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -104,10 +104,10 @@ void OptionHandlerTest::testNumberOptionHandler_max()
{ {
NumberOptionHandler handler("foo", -1, 100); NumberOptionHandler handler("foo", -1, 100);
Option option; Option option;
handler.parseArg(&option, "100"); handler.parse(&option, "100");
CPPUNIT_ASSERT_EQUAL(string("100"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("100"), option.get("foo"));
try { try {
handler.parseArg(&option, "101"); handler.parse(&option, "101");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -119,19 +119,19 @@ void OptionHandlerTest::testNumberOptionHandler_min_max()
{ {
NumberOptionHandler handler("foo", 1, 100); NumberOptionHandler handler("foo", 1, 100);
Option option; Option option;
handler.parseArg(&option, "1"); handler.parse(&option, "1");
CPPUNIT_ASSERT_EQUAL(string("1"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("1"), option.get("foo"));
handler.parseArg(&option, "100"); handler.parse(&option, "100");
CPPUNIT_ASSERT_EQUAL(string("100"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("100"), option.get("foo"));
try { try {
handler.parseArg(&option, "0"); handler.parse(&option, "0");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, "101"); handler.parse(&option, "101");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -145,17 +145,17 @@ void OptionHandlerTest::testUnitNumberOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "4294967296"); handler.parse(&option, "4294967296");
CPPUNIT_ASSERT_EQUAL(string("4294967296"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("4294967296"), option.get("foo"));
handler.parseArg(&option, "4096M"); handler.parse(&option, "4096M");
CPPUNIT_ASSERT_EQUAL(string("4294967296"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("4294967296"), option.get("foo"));
handler.parseArg(&option, "4096K"); handler.parse(&option, "4096K");
CPPUNIT_ASSERT_EQUAL(string("4194304"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("4194304"), option.get("foo"));
handler.parseArg(&option, "K"); handler.parse(&option, "K");
CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo"));
handler.parseArg(&option, "M"); handler.parse(&option, "M");
CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo"));
handler.parseArg(&option, ""); handler.parse(&option, "");
CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0"), option.get("foo"));
} }
@ -165,10 +165,10 @@ void OptionHandlerTest::testParameterOptionHandler_1argInit()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "value1"); handler.parse(&option, "value1");
CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo"));
try { try {
handler.parseArg(&option, "value3"); handler.parse(&option, "value3");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -182,12 +182,12 @@ void OptionHandlerTest::testParameterOptionHandler_2argsInit()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "value1"); handler.parse(&option, "value1");
CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo"));
handler.parseArg(&option, "value2"); handler.parse(&option, "value2");
CPPUNIT_ASSERT_EQUAL(string("value2"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("value2"), option.get("foo"));
try { try {
handler.parseArg(&option, "value3"); handler.parse(&option, "value3");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -205,12 +205,12 @@ void OptionHandlerTest::testParameterOptionHandler_listInit()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "value1"); handler.parse(&option, "value1");
CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("value1"), option.get("foo"));
handler.parseArg(&option, "value2"); handler.parse(&option, "value2");
CPPUNIT_ASSERT_EQUAL(string("value2"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("value2"), option.get("foo"));
try { try {
handler.parseArg(&option, "value3"); handler.parse(&option, "value3");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -224,9 +224,9 @@ void OptionHandlerTest::testDefaultOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "bar"); handler.parse(&option, "bar");
CPPUNIT_ASSERT_EQUAL(string("bar"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("bar"), option.get("foo"));
handler.parseArg(&option, ""); handler.parse(&option, "");
CPPUNIT_ASSERT_EQUAL(string(""), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string(""), option.get("foo"));
} }
@ -236,7 +236,7 @@ void OptionHandlerTest::testFloatNumberOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "1.0"); handler.parse(&option, "1.0");
CPPUNIT_ASSERT_EQUAL(string("1.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("1.0"), option.get("foo"));
} }
@ -244,10 +244,10 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min()
{ {
FloatNumberOptionHandler handler("foo", 0.0); FloatNumberOptionHandler handler("foo", 0.0);
Option option; Option option;
handler.parseArg(&option, "0.0"); handler.parse(&option, "0.0");
CPPUNIT_ASSERT_EQUAL(string("0.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0.0"), option.get("foo"));
try { try {
handler.parseArg(&option, "-0.1"); handler.parse(&option, "-0.1");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -259,10 +259,10 @@ void OptionHandlerTest::testFloatNumberOptionHandler_max()
{ {
FloatNumberOptionHandler handler("foo", -1, 10.0); FloatNumberOptionHandler handler("foo", -1, 10.0);
Option option; Option option;
handler.parseArg(&option, "10.0"); handler.parse(&option, "10.0");
CPPUNIT_ASSERT_EQUAL(string("10.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("10.0"), option.get("foo"));
try { try {
handler.parseArg(&option, "10.1"); handler.parse(&option, "10.1");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -274,19 +274,19 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min_max()
{ {
FloatNumberOptionHandler handler("foo", 0.0, 10.0); FloatNumberOptionHandler handler("foo", 0.0, 10.0);
Option option; Option option;
handler.parseArg(&option, "0.0"); handler.parse(&option, "0.0");
CPPUNIT_ASSERT_EQUAL(string("0.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("0.0"), option.get("foo"));
handler.parseArg(&option, "10.0"); handler.parse(&option, "10.0");
CPPUNIT_ASSERT_EQUAL(string("10.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(string("10.0"), option.get("foo"));
try { try {
handler.parseArg(&option, "-0.1"); handler.parse(&option, "-0.1");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, "10.1"); handler.parse(&option, "10.1");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
@ -300,12 +300,12 @@ void OptionHandlerTest::testLogOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "/tmp/log.txt"); handler.parse(&option, "/tmp/log.txt");
CPPUNIT_ASSERT_EQUAL(string("/tmp/log.txt"), option.get(PREF_LOG)); CPPUNIT_ASSERT_EQUAL(string("/tmp/log.txt"), option.get(PREF_LOG));
CPPUNIT_ASSERT_EQUAL(string(""), option.get(PREF_STDOUT_LOG)); CPPUNIT_ASSERT_EQUAL(string(""), option.get(PREF_STDOUT_LOG));
option.clear(); option.clear();
handler.parseArg(&option, "-"); handler.parse(&option, "-");
CPPUNIT_ASSERT_EQUAL(string(""), option.get(PREF_LOG)); CPPUNIT_ASSERT_EQUAL(string(""), option.get(PREF_LOG));
CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get(PREF_STDOUT_LOG)); CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get(PREF_STDOUT_LOG));
} }
@ -316,42 +316,42 @@ void OptionHandlerTest::testHttpProxyOptionHandler()
CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(handler.canHandle("foo"));
CPPUNIT_ASSERT(!handler.canHandle("foobar")); CPPUNIT_ASSERT(!handler.canHandle("foobar"));
Option option; Option option;
handler.parseArg(&option, "bar:80"); handler.parse(&option, "bar:80");
CPPUNIT_ASSERT_EQUAL(string("bar:80"), option.get(PREF_HTTP_PROXY)); CPPUNIT_ASSERT_EQUAL(string("bar:80"), option.get(PREF_HTTP_PROXY));
CPPUNIT_ASSERT_EQUAL(string("bar"), option.get(PREF_HTTP_PROXY_HOST)); CPPUNIT_ASSERT_EQUAL(string("bar"), option.get(PREF_HTTP_PROXY_HOST));
CPPUNIT_ASSERT_EQUAL(string("80"), option.get(PREF_HTTP_PROXY_PORT)); CPPUNIT_ASSERT_EQUAL(string("80"), option.get(PREF_HTTP_PROXY_PORT));
CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get(PREF_HTTP_PROXY_ENABLED)); CPPUNIT_ASSERT_EQUAL(string(V_TRUE), option.get(PREF_HTTP_PROXY_ENABLED));
try { try {
handler.parseArg(&option, "bar"); handler.parse(&option, "bar");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, "bar:"); handler.parse(&option, "bar:");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, ":"); handler.parse(&option, ":");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, ":80"); handler.parse(&option, ":80");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;
delete e; delete e;
} }
try { try {
handler.parseArg(&option, "foo:bar"); handler.parse(&option, "foo:bar");
CPPUNIT_FAIL("exception must be thrown."); CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) { } catch(Exception* e) {
cerr << e->getMsg() << endl; cerr << e->getMsg() << endl;

79
test/SequenceTest.cc Normal file
View File

@ -0,0 +1,79 @@
#include "Sequence.h"
#include <cppunit/extensions/HelperMacros.h>
using namespace std;
class SequenceTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(SequenceTest);
CPPUNIT_TEST(testParseAndNext);
CPPUNIT_TEST(testParseAndNext2);
CPPUNIT_TEST(testFlush);
CPPUNIT_TEST_SUITE_END();
public:
void testParseAndNext();
void testParseAndNext2();
void testFlush();
};
CPPUNIT_TEST_SUITE_REGISTRATION(SequenceTest);
typedef Sequence<int32_t> IntSequence;
void SequenceTest::testParseAndNext()
{
IntSequence::Value params[] = {
IntSequence::Value(1, 2),
IntSequence::Value(3, 9),
IntSequence::Value(10, 11),
};
IntSequence seq(IntSequence::Values(&params[0], &params[3]));
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)1, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)3, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)4, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)5, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)6, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)7, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)8, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)10, seq.next());
CPPUNIT_ASSERT(!seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)0, seq.next());
}
void SequenceTest::testParseAndNext2()
{
IntSequence::Value params[] = {
IntSequence::Value(1, 2),
};
IntSequence seq(IntSequence::Values(&params[0], &params[1]));
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)1, seq.next());
CPPUNIT_ASSERT(!seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)0, seq.next());
}
void SequenceTest::testFlush()
{
IntSequence::Value params[] = {
IntSequence::Value(1, 2),
IntSequence::Value(3, 9),
IntSequence::Value(10, 11),
};
IntSequence seq(IntSequence::Values(&params[0], &params[3]));
deque<int32_t> r = seq.flush();
int32_t answers[] = { 1, 3, 4, 5, 6, 7, 8, 10 };
CPPUNIT_ASSERT(equal(r.begin(), r.end(), &answers[0]));
}

View File

@ -32,6 +32,10 @@ class UtilTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testAlphaToNum); CPPUNIT_TEST(testAlphaToNum);
CPPUNIT_TEST(testMkdirs); CPPUNIT_TEST(testMkdirs);
CPPUNIT_TEST(testConvertBitfield); CPPUNIT_TEST(testConvertBitfield);
CPPUNIT_TEST(testParseIntRange);
CPPUNIT_TEST(testParseIntRange_invalidRange);
CPPUNIT_TEST(testParseInt);
CPPUNIT_TEST(testParseLLInt);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
private: private:
@ -61,6 +65,10 @@ public:
void testAlphaToNum(); void testAlphaToNum();
void testMkdirs(); void testMkdirs();
void testConvertBitfield(); void testConvertBitfield();
void testParseIntRange();
void testParseIntRange_invalidRange();
void testParseInt();
void testParseLLInt();
}; };
@ -407,3 +415,123 @@ void UtilTest::testConvertBitfield()
Util::toHex(destBitfield.getBitfield(), Util::toHex(destBitfield.getBitfield(),
destBitfield.getBitfieldLength())); destBitfield.getBitfieldLength()));
} }
void UtilTest::testParseIntRange()
{
IntSequence seq = Util::parseIntRange("1,3-8,10");
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)1, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)3, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)4, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)5, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)6, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)7, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)8, seq.next());
CPPUNIT_ASSERT(seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)10, seq.next());
CPPUNIT_ASSERT(!seq.hasNext());
CPPUNIT_ASSERT_EQUAL((int32_t)0, seq.next());
}
void UtilTest::testParseIntRange_invalidRange()
{
try {
IntSequence seq = Util::parseIntRange("-1");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
IntSequence seq = Util::parseIntRange("2147483648");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
IntSequence seq = Util::parseIntRange("2147483647-2147483648");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
IntSequence seq = Util::parseIntRange("1-2x");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
IntSequence seq = Util::parseIntRange("3x-4");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
}
void UtilTest::testParseInt()
{
CPPUNIT_ASSERT_EQUAL((int32_t)-1, Util::parseInt("-1"));
CPPUNIT_ASSERT_EQUAL((int32_t)2147483647, Util::parseInt("2147483647"));
try {
Util::parseInt("2147483648");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
Util::parseInt("-2147483649");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
Util::parseInt("12x");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
}
void UtilTest::testParseLLInt()
{
CPPUNIT_ASSERT_EQUAL((int64_t)-1, Util::parseLLInt("-1"));
CPPUNIT_ASSERT_EQUAL((int64_t)9223372036854775807LL,
Util::parseLLInt("9223372036854775807"));
try {
Util::parseLLInt("9223372036854775808");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
Util::parseLLInt("-9223372036854775809");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
try {
Util::parseLLInt("12x");
CPPUNIT_FAIL("exception must be thrown.");
} catch(Exception* e) {
cerr << *e;
delete e;
}
}